XCode 4 failing to compile a very large array, and questions about NSArray/NSString overhead
I'm new to Objective C and XCode, cur开发者_JS百科rently working on my first iPhone Game. The game must do some very fast spellchecking against a scrabble dictionary of over 250,000 words, ideally fast enough that I can check 100+ strings against the word list in a single frame.
I have written this before in C and actionscript 2 without issue, just using a standard binary search, but I'm not sure the best way to implement this in Objective C with options like NSString and NSArray available.
The biggest problem at the moment is that it won't even compile at all. If I create an NSArray populated with NSStrings, XCode simply hangs but does not crash. I left it compiling for about 30 minutes with no result. The code I was using:
words=[NSArray arrayWithObjects:@"aa", @"aah", ...250,000 words... @"zyzzyvas" ,nil];
When the wordlist is reduced to a couple hundred words, it compiles and works fine.
Can anyone shed some light on why this is failing, or suggest a better way of going about it?
The next thing I'm going to try is splitting the wordlist into many smaller pieces; separated by the first letter and perhaps also the the number of letters, but that means a lot of messing around reformatting huge text files for trial and error which could quite likely hit the same wall.
The other part to this question is a general query about the speed of NSArray and the overhead of NSString compared to an old fashioned array of char pointers, C style. If NSStrings contain even a few extra bytes of header or function pointers or whatever, making 250 thousand of them in an iPhone app is probably the wrong thing to do, right?
Any suggestions at all would be greatly appreciated.
I'd really be tempted to use a database for this - the built-in SQLite being an ideal solution.
That said, if you have your existing C solution to hand, there's no reason why you can't use this pretty much as-is (it's not as if you have to use the Cocoa classes after all), although you'll need to tread carefully in terms of memory utilisation bearing in mind the constraints of the iOS devices.
Messages are translated directly into C function calls, so your code does this:
words = objc_msgSend(NSArray, @selector(arrayWithObjects:), @"aa", @"aah", ...250,000 more arguments...);
When a function is called in C, its parameters are first pushed onto the stack. It's unlikely that you're running out of stack space at just a few hundred words, but entirely possible at 250,000 words. So, you're probably running up against some compiler limit on either the number of parameters or the total size of the parameter data.
There are definitely better ways to do what you're doing. At the very least, use @smorgan's suggestion and read the list from a file. Better would be to use a memory-mapped file so that you don't have to keep the entire thing in memory all the time -- let the OS handle loading and loading parts of the file into memory for you.
Rather than compile hundreds of thousands of static strings into your app, why not keep the word list in a file and read it at launch?
You could solve your compile-time issue by using the NSAarray +initWithContentsofFile:
method to read in the whole array from a property list file.
But, using an NSArray with a hand-coded binary search seems like the wrong tool. Just sticking within the Cocoa Touch Foundation classes, NSSet
seems like a better fit than NSArray
.
In any case you're probably right to be concerned about the overhead of creating that many objects; using your existing C solution or a database as middaparka said both sound like better options.
精彩评论