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.
Related
how can we judge object action performance over Nsarray vs Nsmutablearray and nsdictionary vs nsmutabledictionary
Short answer: You don't. Both NSArray/NSMutableArray and NSDictionary/NSMutableDictionary are "class clusters", or whole families of classes where the system decides at runtime which specific implementation to use based on factors that are not documented. Presumably it takes into account the number of elements, the types of objects stored, and (for dictionaries) the data type of the key values.
The implementation is opaque, and subject to change.
The best you're going to be able to do is to do some testing with different conditions and graph the results.
I have a complex tableview. Objective C
To populate a number of labels in each cell I had a multi-dimension table composed of 2 NSMutableArrays (1 embedded inside the other). The result was an array that had 3 columns per row.
To free up memory I used
[arrayname removeAllObjects];
Well all I can say is that this did absolutely nothing.
This array (which per row was only holding about 130 chars of data and in this sample data I only had 30 rows) was like a virus that's favourite food was memory. It ate chunks of 50mg like there was no tomorrow.
The removeAllObjects did nothing to recover memory.
I have searched high and low and find no clear way to free up memory when you are working with NSMutableArrays and it seems like multi-dimensional ones are cookie monsters.
In the end I removed the multi-dimensional array and just built a single NSMutableArray which was just all of the data concatenated into a string, which I then subStringed out the 3 pieces of data when I needed them.
Memory returned back to normal.
This may not have been the ideal solution. Has anyone found a clear way of releasing the memory of NSMutableArrays ?
It would help if we knew what language you were using. If you're writing in C, just call
free(<array pointer>);
In the end I removed the multi-dimensional array and just built a single NSMutableArray which was just all of the data concatenated into a string, which I then subStringed out the 3 pieces of data when I needed them.
Memory returned back to normal.
This may not have been the ideal solution but it worked
Multi-dimensional NSMutableArray is unusual, but supported. It may not work the way you expect it to; it really is an array of arrays. In many languages, a "2D" array is really a wrapper around a multiplication function. This matters because with NSMutableArray, each subarray could be a different length, and you need to initialize and manage each of them.
But with ARC, the memory will be handled fine. You just have a mistake in your code. You're probably either retaining the subarray somewhere that you didn't mean to, or you aren't waiting for the autorelease pool to drain. But either way, arrays of arrays are fine in Cocoa.
I need to have a few hard coded collection data (ie NSArray, NSDictionary), and I'm wondering what the memory footprint is it like, for example,
- (NSArray *)getDataA
{
NSArray *data = #[ #{#"key": #"value"} ];
return data;
}
And the actual data is way more than the key-value in the above code.
I guess the local variables are stored on stack and the actual value are in heap, but before calling getDataA, do they occupy any memory space?
Thanks!
Keep in mind that a structure such as in the question is created by code executing at runtime, they will not be static. Constant NSStrings are the exception and possibly a few other special cases like some NSNumbers.
Unless you have MBs the size is not really important. Like all optimizations: don't. Do the most clear implementation and then measure.
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.
Wondering, After building nsmutablearray should i convert it to nsarray for performance benefit? If i am going to keep and use that array for quite sometime.
No. The conversion itself will cost time and CPU cycles and you won't gain anything from the conversion.
I would actually say it depends. If I create a NSMutableArray within a method and needs to return it, then generally unless the caller requires the ability to directly modify the array values, I will return the NSMutableArray as a NSArray for the sake of simlicity and to reduce the memory footprint of the application.
However, if I am creating the NSMutableArray for direct consumption within the current method, then I seen no benefit of casting it to a NSArray.