views:

283

answers:

2

I have an Iphone app with a large, nested NSArray of strings. The NSArray goes 3 levels deep, and there are a total of approximately 15,000 strings at the deepest levels. The vast majority of the strings have fewer than 20 characters. Every so often, my app hangs for a while, then resumes working after 5-25 seconds or so. This is obviously unacceptable. If I run the app with only 2,000 of the strings, the hangs become much rarer. So I am pretty sure the large NSArray is causing the problem.

What alternative data structure would be likely to work better? All I need is to quickly read the array from a file when the app starts, then be able to access strings at random from the array. [It's actually a little more complicated than that; I need to be able to grab random strings from pre-determined subsets of the array.] The program might grab a random string as often as once a second.

Incidentally, the NSArray is currently stored in a singleton class.

+1  A: 

While other data structures (trie) do come to mind, the real questions are:

(1) Have you or can you profile with Instruments during these hangs

and with the not-necessarily-correct assumption that the arrays are your problem

(2) What operations are you performing on the arrays?

You don't want to guess about what causes performance issues unless you have no choice, you want to measure. But if you made me guess… I'd wonder if you're running tight on memory, and if the hangs are the system issuing low memory warnings and things cleaning up.

Ken
I know I'm not leaking. Object allocations can be up to about 10MB a minute. Beyond that -- what portions of instruments might give me useful information?
William Jockusch
Time Profiler. What's it doing when it hangs?
Ken
I don't know because try as I might, I can't get time profiler to profile my Ipod touch. It is always greyed out. I did profile it under shark and it was 90%+ PID#0. But I don't know what PID#0 is either.
William Jockusch
+2  A: 

With that many strings, there is no way you have them in a table at once (right???).

You really, really need to put those in a database and access them on-demand. Core Data is tailor made to persisting large object graphs and letting you pull out the parts you care about, quickly, while it caches things behind the scenes for you.

As for instruments, you really want to use Time Profiler to see where the system is spending all its time - preferably on the device itself. You might find a very great deal of time is spent in autoreleasing objects, for example (which the long random pause would seem to be a sign of) - that would correspond to constantly getting rid of large portions of arrays.

Kendall Helmstetter Gelner
I'm not sure what you mean by "in a table." They are in an NSArray which is loaded into memory. Are you saying this could be my problem?
William Jockusch
I am sure that is your problem, or at least it's not a good idea - by "in a table" I mean actually all displayed to the user at once in one UITable. That's what seems very unlikely to me, presenting a table to the user with 10k entries to scroll though. Given you are not going to show them all at once, holding them in a database makes way, way more sense.
Kendall Helmstetter Gelner
This is only around 350KB storage accounted for, so this much memory by itself doesn't seem insane. I think it'd depend what you're doing with it.
Ken
It's not so much the amount of storage as it is the number of objects, where allocating and releasing a ton of tiny blocks of memory can impact performance. If the size is a constant another thing you might consider is using NSMutableArrays and re-using them instead of releasing them, by keeping track of a pool of unused arrays.
Kendall Helmstetter Gelner