views:

574

answers:

6

Hi! I've been developing for the iPhone for quite some time and I've been wondering if there's any array object that uses circular buffer in Obj-C? Like Java's Stack or List or Queue. I've been tinkering with the NSMutableArray, testing it's limits... and it seems that after 50k simple objects inside the array - the application is significantly slowed down.

So, is there any better solution other than the NSMutableArray (which becomes very slow with huge amounts of data). If not, can anyone tell me about a way to create such an object (would that involve using chain (node) objects??).

Bottom line: Populating a UITableView from an SQLite DB directly would be smart? As it won't require memory from an array or anything, but just the queries. And SQLite is fast and not memory grinding.

Thank you very much for you time and attention, ~ Natanavra.

A: 

Objective-C objects are not really "simple," so 50,000 of them is going to be pretty demanding. Write your own in straight C or C++ if you want to avoid the bottlenecks and resource demands of the Objective-C runtime.

A rather lengthy and non-theoretical discussion of the overhead associated with convenience:

http://www.cocoabuilder.com/archive/cocoa/35145-nsarray-overhead-question.html#35128

And some simple math for simple people:

All it takes to make an object as opposed to a struct is a single pointer at the beginning.

Let's say that's true, and let's say we're running on a 32-bit system with 4 byte pointers.

4 bytes x 50,000 objects = 200000 bytes

That's nearly 200MB worth of extra memory that your data suddenly needs just because you used Objective-C. Now compound that with the fact that whatever NSArray you add those objects to is going to double that by keeping its own set of pointers to those objects and you've just chewed up 400MB of RAM just so you could use a couple of convenience wrappers.

Refresh my memory here... Are swap files on hard drives as fast as RAM? How much RAM is there in an iPhone? How many function calls and stack frames does it take to send an object a message? Why isn't IOKit written in Objective-C? How many of Apple's flagship applications that do a lot of DSP use AppKit? Anybody got a copy of otool they can check with? I'm seeing zero here.

Azeem.Butt
Unless you've profiled and proven that your C solution is faster, I wouldn't do that.
Chuck
You'd have to write some pretty terrible code to come up with a C-based linked list implementation that's slower than the amount of Objective-C message passing involved in maintaining an NSArray.
Azeem.Butt
You should read that entire thread, including the message from Chris Kane, before you blithely assume that rolling your own linked list implementation is going to outperform NSArray.
NSResponder
I did read the entire thread, and I see no reason to question my conviction that an NSArray full of 50,000 NSObjects is going to be slower than just about everything else in the world. If you have evidence to the contrary, then you should post it instead of blithely assuming that your snark alone constitutes something of value.
Azeem.Butt
As it happens, an Objective-C object is quite simple. All it takes to make an object as opposed to a struct is a single pointer at the beginning. The idea that Obj-C instances are "heavyweight" is a misconception carried over from deliberate misinformation that was tossed around by the C++ die-hards at the time of Apple's transition to OS X.NSArray is quite efficient for most uses, and it's rather stupid to just write your own container implementation instead of *measuring* to see if NSArray's performance is the bottleneck.
NSResponder
Yeah, so about that evidence... Do you actually have any that might prove objc_msgsend isn't a horrible bottleneck that slows everything it touches to a crawl, or are you just going to keep regurgitating the same NeXT employee litany against logic that's been keeping Objective-C from reaching any degree of popularity outside of the cult that birthed it since 1988?
Azeem.Butt
@NSD: Burden of proof is on the one claiming that there is a slowdown.
Chuck
Chuck, I think Nathan has certainly proven something, although it wasn't what he intended to prove. ;-) Nathan, you might want to refresh your memory on the difference between megabytes and kilobytes. Thanks for the laugh, though. I think I see why Apple decided to dispense with your services.
NSResponder
200000 bytes is 200kB not 200MB - that's quite an important difference.
Greg Beech
+2  A: 

It's trivial to have NSMutable array act like a stack, list, queue etc using the various insertObject:atIndex: and removeObjectAtIndex: methods. You can write your own subclasses if you want to hardwire the behavior.

I doubt the performance problems you are seeing are being caused by NSMutableArray especially if your point of reference is the much, much slower Java. The problem is most likely the iPhone itself. As noted previously, 50,000 objective-c objects is not a trivial amount of data in this context and the iPhone hardware may struggle to managed that much data.

If you need some kind of high performance array for bytes, you could use one of the core foundation arrays or roll your own in plain C and then wrap them in a custom class.

It sounds to me like you need to switch to core data so you don't have to keep all this in memory. Core data will efficiently fetch what you want only when you need it.

TechZen
"much much slower Java". any benchmarks?
Mehrdad Afshari
NSArray is not particularly fast, so while it may not be the sole cause of the performance issue, it's not going to help anything.
Azeem.Butt
I've never seen Java best a compiled language on the same hardware. As NSD has noted, Objective-C's messaging makes it slower than just plain C (which is part of why you can't use it for drivers) but its still faster than a VM by a lot. I think the OP is unconsciously comparing Java's performance on a non-embedded system to Objective-C's performance on the embedded iPhone and assuming the problem is with the language/API instead of the hardware. If he doesn't have a feel for the speed of the hardware he will waste time looking for bottlenecks that don't exist.
TechZen
@TechZen: (nitpicking) Objective-C's messaging does not make it slower than just plain C, because you don't need to use it. Normal function calls are perfectly valid Objective-C, and have the same speed as they would in "normal" C code. One doesn't need to use the feature just because it's there.
Stephen Canon
+3  A: 

Apologies for tooting my own horn, but I implemented a C-based circular buffer in CHDataStructures. (Specifically, check out CHCircularBufferQueue and CHCircularBufferStack.) The project is open source and has benchmarks which demonstrate that a true circular buffer is quite fast when compared to NSMutableArray in the general case, but results will depend on your data and usage, as well as the fact that you're operating on a memory-constrained device (e.g. iPhone). Hope that helps!

Quinn Taylor
Thanks! That sounds like what I'm looking for... although it's not critical, I want to find a way to be able to display 50k-100k of objects easily on a UITableView.
natanavra
+4  A: 

If you're seeing performance issues, measure where your app is spending its time, don't just guess. Apple provides an excellent set of performance measurement tools.

NSResponder
While parroting Knuth is frequently both safe and impressive to others, there's no guesswork involved when you're talking about shoving multiple tens of thousands of objects into a managed array on a resource-starved embedded system.
Azeem.Butt
I'm sure you think that was a clever gybe on your part, but you're mistaken. I have a great deal of first-hand experience with people new to Objective-C making guesses as to where their performance issues were. I spent three and a half years at Apple, including over a year as the sole Cocoa engineer in DTS.
NSResponder
@NSResponder I'm not really new to Obj-C and I don't have any performance Issues. I did test it with instruments and it's not a guess... The problem is with managing a few hundred thousand of objects and displaying them.I have an SQLite database that helps storing and retrieving everything easily but the question is - how would you display all that mass of data inside a UITableView. So one option would be always retrieving stuff from my SQLite db whenever I want to display something. The other option I thought of was using a circular buffer object.NSD is right, and your answer is offtopic.
natanavra
Nathan, I'm sorry you got canned for your refusal to update your skills, but that's off-topic here. Those former NeXT employees that you're disparaging rescued Apple from the impending doom that your faction had made nearly inevitable. I had a great time there for three and a half years, until I left to work on a hardware startup.
NSResponder
A: 

You can use STL classes in "Objective-C++" - which is a fancy name for Objective-C making use of C++ classes. Just name those source files that use C++ code with a ".mm" extension and you'll get the mixed runtime.

Scott Lahteine
A: 

From what I've been thinking it seems that going for Quinn's class is the best option possibly. I have another question - would it be faster or smarter to load everything straight from the SQLite DB instead of creating an object and pushing it into an array?

Thank you in advance, ~ Natanavra.

natanavra