I am writing an application that I'd like to speed up. One way I have thought to do this is by switching from using NSArray and NSMutableArray to using straight c-style arrays of pointers.
I had tried naively to just do:
MyObject** objects = (MyObject**) malloc(N/2*sizeof(MyObject*))
This reports a compiler error when using ARC as it doesn't know what to do with a ** object;
this can be fixed by adding a bridge directive.
My question is how is this memory being handled and how to do memory management mixing C and Objective-C objects.
Two solutions are
MyObject* __weak* objects = (MyObject* __weak*) malloc(N/2*sizeof(MyObject*));
MyObject* __strong* objects = (MyObject* __strong*) malloc(N/2*sizeof(MyObject*));
What are the differences between those two arrays and how do I go about freeing/releasing them when done. Are NSArrays optimized to the point where this wouldn't result it much of a speed up?
Are NSArrays optimized to the point where this wouldn't result it much of a speed up?
Yes.
You should profile your code in Instruments -- chances are that even if you make heavy use of arrays, you're going to find that your code spends most of its time in places other than NSArray methods like -objectAtIndex:.
Taking that a step further, you should really be able to tell us whether NSArray is optimized sufficiently that you don't need to improve it. If you're looking to speed up your code by replacing NSArray, you should have already profiled your code and identified the expensive parts. Don't just guess at what needs to be improved; measure it.
Related
I am trying to squeeze every bit of efficiency out of my application I am working on.
I have a couple arrays that follow the following conditions:
They are NEVER appended to, I always calculate the index myself
The are allocated once and never change size
It would be nice if they were thread safe as long as it doesn't cost performance
Some hold primitives like floats, or unsigned ints. One of them does hold a class.
Most of these arrays at some point are passed into a glBuffer
Never cleared just overwritten
Some of the arrays individual elements are changed entirely by = others are changed by +=
I currently am using swift native arrays and am allocating them like var arr = [GLfloat](count: 999, repeatedValue: 0) however I have been reading a lot of documentation and it sounds like Swift arrays are much more abstract then a traditional C-style array. I am not even sure if they are allocated in a block or more like a linked list with bits and pieces thrown all over the place. I believe by doing the code above you cause it to allocate in a continuous block but i'm not sure.
I worry that the abstract nature of Swift arrays is something that is wasting a lot of precious processing time. As you can see by my above conditions I dont need any of the fancy appending, or safety features of Swift arrays. I just need it simple and fast.
My question is: In this scenario should I be using some other form of array? NSArray, somehow get a C-style array going, create my own data type?
Im looking into thread safety, would a different array type that was more thread safe such as NSArray be any slower?
Note that your requirements are contradictory, particularly #2 and #7. You can't operate on them with += and also say they will never change size. "I always calculate the index myself" also doesn't make sense. What else would calculate it? The requirements for things you will hand to glBuffer are radically different than the requirements for things that will hold objects.
If you construct the Array the way you say, you'll get contiguous memory. If you want to be absolutely certain that you have contiguous memory, use a ContiguousArray (but in the vast majority of cases this will give you little to no benefit while costing you complexity; there appear to be some corner cases in the current compiler that give a small advantage to ContinguousArray, but you must benchmark before assuming that's true). It's not clear what kind of "abstractness" you have in mind, but there's no secrets about how Array works. All of stdlib is open source. Go look and see if it does things you want to avoid.
For certain kinds of operations, it is possible for other types of data structures to be faster. For instance, there are cases where a dispatch_data is better and cases where a regular Data would be better and cases where you should use a ManagedBuffer to gain more control. But in general, unless you deeply know what you're doing, you can easily make things dramatically worse. There is no "is always faster" data structure that works correctly for all the kinds of uses you describe. If there were, that would just be the implementation of Array.
None of this makes sense to pursue until you've built some code and started profiling it in optimized builds to understand what's going on. It is very likely that different uses would be optimized by different kinds of data structures.
It's very strange that you ask whether you should use NSArray, since that would be wildly (orders of magnitude) slower than Array for dealing with very large collections of numbers. You definitely need to experiment with these types a bit to get a sense of their characteristics. NSArray is brilliant and extremely fast for certain problems, but not for that one.
But again, write a little code. Profile it. Look at the generated assembler. See what's happening. Watch particularly for any undesired copying or retain counting. If you see that in a specific case, then you have something to think about changing data structures over. But there's no "use this to go fast." All the trade-offs to achieve that in the general case are already in Array.
This question already has answers here:
Objective-C. Property for C array
(4 answers)
Closed 8 years ago.
I have a custom struct for a world tile in an iOS game. I want to store multiple WorldTiles in an array but am not sure what the most efficient way is. It's an infinite-map style game and I'm loading only chunks around the player, so I want the fastest way of storing the data.
I could store this in a c-based multidimensional array (WorldTile tiles[16][16]) but I don't see a way to make it an #property for easier access outside the class, or I could wrap this using NSValue and store in an NSArray but that seems like overhead I don't need.
typedef struct {
b2Vec2 coord;
float height;
float temperature;
} WorldTile;
How can I either store the multi-dimensional array as an #property, or is the performance cost of wrapping it with an NSValue not a big deal?
I think the issue is with "overhead I don't need". Try using objects first, determine performance issues empirically, then tune your objects, then resort to C (then become surprised that the object overhead you were concerned about is not nearly as big of a deal as one would have thought in the last century).
The OO way is that the World is singular, but has a collection of things in it. That's an NSArray of Things. Those things in turn probably consist of a collection of other things, so Thing has an NSArray property of OtherThings. Multidimensionality achieved, but more importantly, object orientation achieved.
Is the world huge? It should only be built based on proximity to the player? That's fine. Things can be designed to be just stub-Things, which only know location, but initialize themselves when the user becomes proximal. You'll be much more able to understand and therefore optimize this code. In this way, the object oriented system is going to be faster because it allows you the expressive power to make a faster design without doing mental gymnastics.
I am currently working on a Conway's Game of Life simulator for the iPhone and I had a few questions about memory management. Note that I am using ARC.
For my application, I am going to need a large amount of either C style structs or Objective-C objects to represent cells. There may be a couple thousand of these, so obviously, memory management came to mind.
Structs My argument for structs is that the cells do not need typical OO properties. The only thing that they will be holding is two BOOL values, so there will not be huge amount of memory chewed up by these cells. Also, I need to utilize a two-dimensional array. With structs, I can use the C-style 2d arrays. As far as I know, there is no replacement for this in Objective-C. I feel that it is overkill to create an object for just two boolean values.
Objective-C objects My argument (and most other people's) is that the memory management around Objective-C objects is very easy and efficient with ARC. Also, I have seen arguments that a struct is not such a big memory reduction to an object.
So, my question. Should I go with the old-school, lean, and compatible with two-dimensional array structs? Or should I stick with the typical Objective-C objects and risk the extra memory used.
Afterthoughts: If you recommend Objective-C objects, provide an alternate storage method that represents a two-dimensional array. This is critical and is one of the biggest downsides of going with Objective-C objects.
Thankyou.
"Premature optimization is the root of all evil"... If you are trying to build a Game of Life server with 100,000 users playing concurrently, memory footprint might matter. For a single-person implementation on any modern device, even a mobile one, memory size is pretty academic.
Therefore, do whatever either gets the game up and running fastest or (better) makes the code most readable and maintainable. Human cycles cost more than computer cycles. Suppose you needed a third boolean for each cell of the game... wouldn't an object you could extend save a ton of time rather than hardcoded array indices? (A struct is a lot better than an array of primitives for this reason...)
I've certainly used denser representations of data when I need to, but the overhead in programmer time has to be worth it. Just my $.02...
If it is just 2 BOOL values that you are going to store for every cell, then you could just use an array of integers to do the job. For example:
Let us assume that the two bool values are boolX and boolY, we could combine them into an int as:
int combinedBool = boolY + (10*boolX);
So you can retrieve the two bool values like:
BOOL boolX, boolY;
boolX = combinedBool/10;
boolY = combinedBool%10;
And then you can store the whole board in the form a single dimension array of integers with the index of each cell represented by ((yIndex*width)+xIndex) where width is the number of cells left-to-right on your board and, xIndex and yIndex represent the X and Y coordinates of the cell on your board.
Hope this helps with your memory management and cell organisation.
You could build one and test it's size with malloc_size(myObject). Thousands of pairs of bools will be small enough. In fact, you'll be able to make the objects larger and enjoy the benefits of the OO design. For example, what if the cells also kept pointers to their neighboring cells. The cells could compute their own t+1 state with cached access to their neighbors.
I'm wondering what the most applicable kind of buffer implementation is for audio data in objective-c. I'm working with audio data on the iPhone, where I do some direct data manipulation/DSP of the audio data while recording or playing, so performance matters. I do iPhone development since some months now. Currently I'm dealing with c-arrays of element type SInt16 or Float32, but I'm looking for something better.
AFAIK, the performance of pointer-iterated c-arrays is unbeatable in an objective-c environment. However, pointer arithmetic and c-arrays are error prone. You always have to make sure that you do not access the arrays out of their bounds. You will not get a runtime error immediately if you do. And you have to make sure manually that you alloc and dealloc the arrays correctly.
Thus, I'm looking for alternatives. What high performance alternatives are there? Is there anything in objective-c similar to the c++ style std::vector?
With similar I mean:
good performance
iteratable with pointer-/iterator-based loop
no overhead of boxing/unboxing basic data types like Float32 or SInt16 into objective-c objects (btw, what's the correct word for 'basic data types' in objective-c?)
bounds-checking
possibility to copy/read/write chunks of other lists or arrays into and out of my searched-for list implementation
memory management included
I've searched and read quite a bit and of course NSData and NSMutableArray are among the mentioned solutions. However don't they double processing cost because of the overhead for the boxing/unboxing of basic data types? That the code looks outright ugly like a simple 'set'-operation becoming some dinosaur named replaceObjectAtIndex:withObject: isn't of my concern, but still it subtly makes me think that this class is not made for me.
NSMutableData hits one of your requirements in that it brings Objective-C memory management semantics to plain C buffers. You can do something like this:
NSMutableData* data = [NSMutableData dataWithLength: sizeof(Float32) * numberOfFloats];
Float32* cFloatArray = (Float32*)[data mutableBytes];
And you can then treat cFloatArray as a standard C array and use pointer iteration. When the NSMutableData object is dealloc'ed the memory backing it will be freed. It doesn't give you bounds checking, but it delivers memory management help while preserving the performance of C arrays.
Also, if you want some help from the tools in ironing out bounds-checking issues read up on Xcode's Malloc Scribble, Malloc Guard Edges and Guard Malloc options. These will make the runtime much more sensitive to bounds problems. Not useful in production, but can be helpful in ironing out issues during development.
The containers provided in the Foundation framework have little to offer for audio processing, being on the whole rather heavy-weight, nor providing extrinsic iterators.
Furthermore, none of the audio APIs in iOS or MacOSX that interact with buffers of samples are Objective-C - based, or take any parameters of Foundation framework containers.
Most likely, you would want to make use of the Accelerate Framework for DSP operations, and its APIs all work on arrays of floats or int16s.
Whilst all of the APIs are C-style, C++ and STL is the obvious weapon of choice for your requirements, and interworks cleanly with the rest of an application in the guise of Objective-C++. STL frequently compiles down to code which is about as efficient as hand-crafted C.
To memory-manage your buffers, perhaps use std::array - if you want bounds checking or std::shared_ptr or std::unique_ptr with a custom deleter if you're not worried.
Places where an iterator is expected - for instance algorithm functions in <algorithm> - can usually also take pointers to basic types - such as your sample buffers.
I have a question regarding NSArray and NSMutableArray. I understand the difference between two primarily that NSArray is immutable and NSMutableArray is mutable. And as far as my research goes, there performance is kind of same too. There is one thing that I could not find a good answer for and that is if NSMutableArray uses more memory than NSArray and if NSMutableArray is somehow harsher on memory than NSArray.
I would really appreciate the suggestions and explanation.
Thanks
Vik
NSMutableArray uses slightly more memory for two (er, four, see comments) reasons:
1) Because it can change size, it can't store the contents inside the object and must store a pointer to out of line storage as well as the extra malloc node for the storage
2) Because it would be very slow to resize one element at a time as things are added, it resizes in chunks, which may result in some unused space.
It's like wondering about the difference between a standard array or a std::vector. A mutable data structure does require to do more things, not primarily memory (as the one required by NSMutableArray and NSArray could be equal) but it requires to be dynamically resizable and to manage all specific operations like insertions and removals which are not necessary with an immutable array: the dimension is decided when the object is allocated at it is constant.
For normal use there is no noticeable performance difference.
However, If you return an NSArray from a method that internally uses a mutable array for building the response, then I found that a copy of the temporary array can take significant amount of time.
In some instances in DTCoreText I found the [NSMutableArray copy] to NSArray would take 40% of the method time in Instruments. I.e. Returning the mutable array halved the method time.
So when evaluating NSArray versus mutable performance I recommend you direct your attention towards avoiding copying objects. In tight loops or internal methods you should prefer to avoid copying.