The Playground
An application that I’m currently working requires making the drop to the CoreFoundation level so out of curiosity I decided to contrast and compare the performance difference associated with using the Foundation-level NSArray
object versus its CoreFoundation counterpart – CFArray
. To be more precise, in this test we are exploring the performance difference of iterating over the mutable version of both objects, inserting a string, getting the array count (to replicate a real-world scenario where the array size is not given) and retrieving the element at index. This is a brutally simple test, but will hopefully provide at least some insight into how fast each method really is in comparison.
So let’s go over the CFArray
code. In the CoreFoundation version, we first create a mutable CFArray (CFMutableArray)
via the CFArrayCreateMutable()
function call, providing the allocator, array size and the callback function. We then setup a very conventional-looking for
loop, iterating over the array the number of time indicated by arraySize
(this number will change in our tests). A string is then created and appended to the array and released. You might notice that we actually create and Objective-C string literal and transfer the ownership over to CoreFoundation via CFBridgingRetain()
. This means that ARC will no longer take care of releasing the string for us and we must do so explicitly with CFRelease()
. An alternative to this is to use create a string with a CoreFoundation call to CFStringCreateWithCString()
(which is commented out), but this method is much slower and we are interested in comparing the array performance, not string allocation performance. The second portion of the code will get the array count, setup another loop and get the value at index with every iteration. We don’t actually do anything with the string.
The Objective-C Foundation counterpart is very similar in nature but removes the need for CFRelease()
as we are under ARC. Most of this code is pretty self-explanatory so we won’t go through it in detail. One thing to point out, however, is that with Foundation you have the option of using Fast Enumeration, which will actually give you some performance gains, as we’ll see later on. This is commented out beside the conventional for
loop.
The Results
The Conclusion
So as you can see from the test results, Fast Enumeration is clearly the best course of action for pretty much any occasion. However, if you absolutely MUST use CoreFoundation, then you’ll be relieved to know that it at least won’t cause slow downs in terms of performance but it will inherently burden you with manual memory management and sporadic EXC_BAD_ACCESS crashes that general accompany CFRelease()
calls. The takeaway from this experiment, is that it really doesn’t matter which alternative you choose, the likelihood of either one playing a significant role in your application’s performance bottleneck is close to zero. These test were solely based on my curiosity and I hope they can bring value to someone else as well.