What are the differences between NSArray and CCArray? Also, in what cases will one be preferred to the other with respect to game programming?
CCArray emulates NSMutableArray. It is a wrapper around a C array (memory buffer). It was developed and is used internally by cocos2d because NSMutableArray was deemed too slow. However the performance improvement is minimal. Any use cases (features) of CCArray that cocos2d itself doesn't use remain a potential source of issues, including weird and hard to debug issues or terrible performance characteristics.
The most important performance critical aspect is reading the array sequential. In my latest tests that's an area where CCArray (no longer?) excels. Specifically fast enumeration: NSMutableArray is around 33 times faster!
CCArray is a perfect example why one should not reinvent the wheel, specifically when it comes to storage classes when there is already a stable, proven, and fast solution available (NSMutableArray). Any speed advantage it may have once had is long gone. What remains is a runtime behavior you will not want to deal with, including some extremely bad performance characteristics (insertion, fast enumeration).
Long story short: do not use CCArray in your own code! Treat CCArray like an internal, private class not to be used in user code (except where unavoidable, ie children array).
NSMutableArray is THE array reference implementation everyone should be using because it's extremely well tested, documented, and stable (both in terms of runtime behavior and speed).
Check it....
http://www.learn-cocos2d.com/2010/09/array-performance-comparison-carray-ccarray-nsarray-nsmutablearray/
Hope this help
Enjoy Programming
CCArray
http://www.cocos2d-x.org/embedded/cocos2d-x/d9/d2e/classcocos2d_1_1_c_c_array.html
In cocos2d-x CCArray is mutable, i.e. you can add elements to it. To create CCArray instance without capacity, you can use CCArray::array() constructor. CCMutableArray is template-based container that can store objects of the same type. CCArray stores objects as CCObject instances, so you have to cast them after getting from CCArray instance
The NSArray class contains a number of methods specifically designed to ease the creation and manipulation of arrays within Objective-C programs.
Related
There are tons of articles and blog posts over the internet telling that mutable objects are bad and that we shouldn't use them and therefore we shall make all our objects immutable.
I have nothing against this except that the topic has gone so far that some people might be "tricked" into thinking that mutable objects shall never be used at all.
When do we have to resort to use mutable objects? What are the common kinds of problems that are unsolvable without using mutable state?
As to your fear, it's common. Every concept gets taken by some as to mean that nothing else shall ever be done, for any reason.
These are the people who try to make requirements fit their ideology, rather than the other way around (a.k.a. they're not pragmatic).
When to use mutables? Basically when you feel like it, when you think it makes sense.
Prime example is in low memory and high performance situations where creating a new instance that's identical except for one little thing from the old one is too expensive in either memory and/or CPU cycles.
For the c++ STL, there is a de-facto standard location (besides the de-jour standard, I mean) to find information about the complexity guarantees of standard container operations.
Is there an analogous, web-accessible document listing complexity guarantees for NSArray, NSDictionary, etc.?
For example, I cannot find a reference that gives complexity for [NSArray count]
Correct. There isn't one. C++ / the STL (based on my limited understanding) have a significant performance focus. Objective-C / Foundation basically don't.
NSArray, NSDictionary and friends are interfaces. They tell you how to use them, not how they behave. This gives them the freedom to switch implementation under the hood for performance reasons. The point is, you don't need to care, and this won't be specified in the API so you can't even if you want to ;)
For a really good read on this subject, highlighting implementation switches, and with a rough comparison between Foundation classes and STL / C data structures, check out the Ridiculous Fish (by someone on the Apple AppKit team) blog post about "Our arrays, aren't"
Is there an analogous, web-accessible document listing complexity
guarantees for NSArray, NSDictionary, etc.?
No. If you understand what the different containers do, you'll have a pretty good idea of how they behave (e.g. dictionary == map -> nearly constant-time lookups). But don't assume that you know exactly how these structures behave, because they may change their behavior based on circumstances. In other words, a class like NSArray may not be (certainly isn't) implemented as an actual array in the sense of a C-style array even though it has that same "ordered sequence of elements" behavior.
You can, of course, analyze the complexity of your own code: your own binary search through an NSArray is always going to take O(log n) operations any way you slice it. Just don't assume that inserting an element into an NSMutableArray is going to require moving all the subsequent elements, because your "array" might really be a linked list or something else.
This question is just out of curiosity but, how is NSSet implemented? What data structure is behind it and what are the access times for adding and removing elements? If I had to guess, I'd say it was some sort of hashtable/dictionary data structure, but in that case why differentiate between NSSet and NSMutableSet?
Well, as Bavarious pointed out in a comment, Apple's actual CoreFoundation source is open and available for your perusal too. NSSet is implemented on top of CFSet, whose code is generated (as is that of CFDictionary) from a hash table template, using CFBasicHash to do the work.
The difference between mutablility and immutability seems to be the matter of a flag in the structure (line 91 of CFBasicHash.h), and from my reading so far just affects calls to functions such as CFBasicHashAddValue; there's a simple check for the mutability. It seems likely, however, that Cobbal is right about the copy/retain behavior between the two (I just haven't read that far yet).
PREVIOUSLY:
I find it interesting and educational occasionally to peruse the GNUstep sources when I'm wondering about implementation details. They are, of course, not at all guaranteed to be implemented the way that Apple did it, but they can be helpful in some cases. Their version of Foundation: http://gnu.ethz.ch/debian/gnustep/gnustep-base-1.20.0/Headers/Foundation/ (I hope that's the most recent version. If not, someone please correct me.)
To answer the second half of your question: one benefit of having a non-mutable version is that it allows for a very fast copy method that simply calls retain.
I find this link to be an interesting answer to your question. Apple's data structures (NSArray, NSSet, NSDictionary, etc.) are not implemented in a straightforward and "standard way." In most cases, they perform in the same way any other set would perform, but overall, they optimize automatically for the best performance. So, in truth, it's rather difficult to say. While Apple provides documentation on the efficiency of arrays in CFArray.h (equivalent for NSArrays), it offers no such documentation on the efficiency of sets, though you're free to poke around /System/Library/Frameworks/CoreFoundation.framework/Headers/ to look through other data structure implementations.
In addition, there has to be a distinction between a set and its mutable counterpart, just as there is a distinction between NSString and NSMutableString, NSArray and NSMutableArray, and NSDictionary and NSMutableDictionary (among others). For data structures and strings (and few other classes), Apple offers 'readonly' versions of classes to retain generality, along with standard 'mutable' counterparts for manipulation. It's simply Apple's standard practice.
I am fairly new to Objective-C and was wondering what the best way to manage collections of tuples was. In C I would use a 2D array or a struct.
Should I be creating objects to contain these tuples? It seems like overkill for just sorting lists or is there no real extra load generated by object initialisation?
There definitely is some overhead in the generation of objects. For a small number of objects, then using ObjC data structures is still appropriate. If you have a large number of tuples, I would manage them in a C array of structs. Remember, Objective-C is really just C. It is appropriate and common to use C constructs in Objective-C (to a point; learning where that point is represents a major milestone in becoming a good Objective-C developer).
Typically for this kind of data structure, I would probably create a single Objective-C object that managed the entire collection. So external callers would see an Objective-C interface, but the internal data would be stored in a more efficient C structure.
If it is common to access a lot of tuples quickly, my collection object would probably provide "get" methods similar to [NSArray getObjects:range:]. ObjC methods that begin with "get" indicate that the first parameter is a pointer that will be overwritten by the method. This is commonly used for high-performance C-like access to things managed by an ObjC object.
This kind of data structure is exactly the way ObjC developers merge the elegance and maintainability of ObjC with the performance and simplicity of C.
I think you'll have to settle for an NSArray of NSArray objects, or maybe an NSArray of NSDictionary objects. You can always roll your own class, or do it the way you would do in C.
There are a couple different ways you could go about this:
CoreData. While it's not technically a database, it can behave a lot like one. If you don't need persistence between app runs, then consider using the NSInMemoryStoreType store type, as opposed to an NSSQLiteStoreType or other option. However, if you're going to want to join tuples together, using CoreData will absolutely not work (this, IMO, is the main reason why CoreData is not a database).
Use a real database. SQLite ships on every Mac and iPhone and is pretty easy to use if you use wrappers like FMDB or SQLite Persistent Objects or PLDatabase or EGODatabase or the GTMSQLite wrapper by Google.
A tuple is really just a collection of key-value pairs, so you could just use an NSMutableArray of NSMutableDictionaries. You obviously won't get to use SQL syntax, and any joins/queries you have to run yourself, but this would definitely have the easiest setup.
Write a tuple class and store those in an NSMutableArray (similar to #3, just enforcing a common set of attributes on your tuples).
I want to perform the same action over several objects stored in a NSSet.
My first attempt was using a fast enumeration:
for (id item in mySetOfObjects)
[item action];
which works pretty fine. Then I thought of:
[mySetOfObjects makeObjectsPerformSelector:#selector(action)];
And now, I don't know what is the best choice. As far as I understand, the two solutions are equivalent. But are there arguments for preferring one solution over the other?
I would argue for using makeObjectsPerformSelector, since it allows the NSSet object to take care of its own indexing, looping and message dispatching. The people who wrote the NSSet code are most likely to know the best way to implement that particular loop.
At worst, they would simply implement the exact same loop, and all you gain is slightly cleaner code (no need for the enclosing loop). At best, they made some internal optimizations and the code will actually run faster.
The topic is briefly mentioned in Apple's Code Speed Performance document, in the section titled "Unrolling Loops".
If you're concerned about performance, the best thing to do is set up a quick program which performs some selector on the objects in a set. Have it run several million times, and time the difference between the two different cases.
I too was presented with this question. I find in the Apple docs "Collections Programming Topics" under "Sets: Unordered Collections of Objects" the following:
The NSSet method objectEnumerator lets
you traverse elements of the set one
by one. And
themakeObjectsPerformSelector: and
makeObjectsPerformSelector:withObject:
methods provide for sending messages
to individual objects in the set. In
most cases, fast enumeration should be
used because it is faster and more
flexible than using an NSEnumerator or
the makeObjectsPerformSelector:
method. For more on enumeration, see
“Enumeration: Traversing a
Collection’s Elements.”
This leads me to believe that Fast Enumeration is still the most efficient means for this application.
I would not use makeObjectsPerformSelector for the simple reason that it is the kind of call that you don't see all that often. Here is why for example - I need to add debugging code as the array is enumerated, and you really can't do that with makeObjectsPerformSelector unless you change how the code works in Release mode which is a real no no.
for (id item in mySetOfObjects)
{
#if MY_DEBUG_BUILD
if ([item isAllMessedUp])
NSLog(#"we found that wily bug that has been haunting us");
#endif
[item action];
}
--Tom
makeObjectsPerformSelector: might be slightly faster, but I doubt there's going to be any practical difference 99% of the time. It is a bit more concise and readable though, I would use it for that reason.
If pure speed is the only issue (i.e. you're creating some rendering engine where every tiny CPU cycle counts), the fastest possible way to iterate through any of the NSCollection objects (as of iOS 5.0 ~ 6.0) is the various "enumerateObjectsUsingBlock" methods. I have no idea why this is, but I tested it and this seems to be the case...
I wrote small test creating collections of hundreds of thousands of objects that each have a method which sums a simple array of ints. Each of those collections were forced to perform the various types of iteration (for loop, fast enumeration, makeObjectsPerformSelector, and enumerateObjectsUsingBlock) millions of times, and in almost every case the "enumerateObjectsUsingBlock" methods won handily over the course of the tests.
The only time when this wasn't true was when memory began to fill up (when I began to run it with millions of objects), after which it began to lose to "makeObjectsPerformSelector".
I'm sorry I didn't take a snapshot of the code, but it's a very simple test to run, I highly recommend giving it a try and see for yourself. :)