What is the computational complexity of NSDictionary's -allKeys method? - objective-c

What is the computational complexity of NSDictionary's -allKeys method?
I would assume it to be O(1) as NSDictionary probably keeps it internally somewhere but you never know :). I tried to look in documentation (NSDictionary and Collections guide) and coundn't find the answer.
Maybe there is some cheat sheet with computational complexities of Cocoa collections' methods?
EDIT:
As was pointed out by Gwendal Roué my question is a bit vague. So I should probably rephrase it like this:
Did someone make measurements of computational complexity of NSDictionary class for some given set of methods and objects and in particular for -allKeys?
EDIT2:
As was pointed out by Chris Devereux these measurements will be implementation dependent but I think it would be nice if someone could share some tables/measurements just to have some approximate numbers.

Go read this wonderful article that explains how NSArray changes its underlying implementation depending on the number of elements it contains: http://ridiculousfish.com/blog/posts/array.html
After that, you'll understand why Apple doesn't document the complexity of its collection classes, including NSDictionary.

Related

Object creation using NSNumber literals

what is the difference between these two approaches for objection creation?
NSNumber *aInt= #54;
NSNumber *aInt= [NSNumber numberWithInt:54];
I know that first approach is NSNumber literal and second is NSNumber class methods. Both are used to create an NSNumber object. But which approach is better?
if i creates object using literal style then how memory is allocated to it? How it is differ then second approach? Please suggest me some key point about these concepts so that i prefer better approach to create NSNumber object.
I know that object created at runtime. Does literals objects are also created at runtime? please provide some essential key points to clear my doubt.
They are identical. In fact they are translated to the same code during compilation.
I always go for the literal because it's easier to read.
What is the difference between these two approaches for objection
creation?
They are Identical.
Answers for:
No. 1:
Using #-prefix will automatically wrap scalar types like int or float.
No. 2:
Using numberWith[type] creates NSNumber specifically and therefor easy to distinguish.
I'm not really sure about memory management of it, but i think, talking about memory allocation it's just the same.
I personally use numberWith[type] because it's more distinguishable (for me), i mean the types it holds and i dont have to worry about backward compatibility, but still i have the knowledge about the literals so i dont have any issue using it.
Better approach is very hard to answer, it's completely up to you/to the developer.
You might also want to check this link
And please, avoid asking too many questions in one post. Cheers! :)

How can I understand the performance tradeoffs in Cocoa library classes?

Today I was asked how long an NSMutableDictionary insertion takes, were that dictionary to contain 1,000,000 elements. Not coming from a computer science background, I had absolutely no idea. I was surprised to learn that it completes in (what I now understand to be called) O(n) time. Great. Wonderful.
How could someone know that, definitively?
Obviously, one could just write dozens and dozens of tests against every single Cocoa class and chart out all the time data. I'll be sure to get around to that when I have a few weeks of free time. Barring all of that...
Is this just super obvious to someone with a computer science
background?
Does Apple publish documentation that explains
this?
Does his knowledge imply that he, being a computer
science expert, did his own testing to discover this?
What you are asking about is called the "complexity" of an algorithm. It is language independent; NSDictionary time complexity is no different than any other associative dictionary such as C++ std::map. However, that doesn't mean that an NSDictionary filled with some objects is guaranteed to be able to perform insert, search, or delete operations as quickly as an std::map; all it means is that the time it takes to do those operations is linear (O(n)), on worst case, in relation to the number of elements (the n part of O(n)). Dictionary insertion could be O(1), which is constant time (operation takes the same amount of time independent of the number of elements in the dictionary) if there were no hash collisions.
The "algorithm" employed by an NSDictionary is called a Hash Table. A hash table does insertion by hashing the key input (a constant time operation), then resolving collisions, an O(n) operation. Hopefully you can see that, in the worst case, all of your insert operations will collide, which is O(n).
Tables/hashing algorithms can of course be specialized to reduce collisions within a specific set of data, but NSDictionary just uses the objects hash method of your key objects, which you can override for your NSObject subclasses if you need some sort of specialization (probably not).
Since it is a general purpose dictionary and not specialized for a specific set of data, we don't necessarily need to know the implementation details of NSDictionary (Apple's documentation for NSDictionary doesnt mention specifics) to know that these operations will be O(n). Neither do we have to run "tests" to discover the complexity.

differences between NSArray and CCArray

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.

objective-c complexity reference

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.

NSSet implementation

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.