Sorry for the vague title, but not quite sure how to summarize this one.
The facts are:<ul><li>I have a game that's been approved by Apple and is on the App Store.</li> <li>It is a universal app. It uses textures designed for 320x480 on small screens, and uses larger textures (roughly four times as large) on retina and iPad screens.</li> <li>While developing it, I would sometimes see low-memory warnings in the console log, but after reading about these it seemed like they were often somewhat spurious/unimportant, and in any event I was not having crashes, and my testers on a variety of devices (iPod Touch 2nd gen, iPod Touch 4th gen, iPhone3, iPhone4, iPad1, iPad2) were not seeing crashes.</li> <li>When I started distributing the app to a wider set of beta testers through TestFlightApp, I got reports of some people seeing crashes as the app was loading, or very early after the user had chosen a level from the main menu and the app was loading the level textures. We discovered that if these users just restarted their devices, they didn't have problems any more. Since this was the first time we had seen problems like this, we attributed it to something TestFlightApp was doing, some funny state it was leaving the device in after the install (we talked to TestFlightApp about this and they had never heard of such a thing).</li> <li>As stated, Apple approved the app and it's on the App Store. Soon after it went live, we got reports from some iPad1 users that it was crashing for them on app load, or soon thereafter, same kind of thing as we saw with certain TestFlightApp users. And again similar to the TestFlightApp users, these customers reported that restarting would often fix the problem. But it wasn't as nice because the problem tended to appear again. One of these users sent me several LowMemory...log files that she got off her PC after synching her iPad. There were about 10 such files, and <em>none</em> of them listed my program in the Processes list. Instead it showed other programs marked as either (active) or (jettisoned), and the "Largest Process" could be anything from MobileSafari to Kobo, but again my own app was never listed. So, I didn't understand that, but the bottom line seems to be that, for this user at least, something is pushing the memory over some limit where my app won't run well.</li> <li>I have since gone back and talked to one of the TestFlightApp beta testers, and it turns out that he does indeed sometimes get the app crash again, so it wasn't just some residue from TestFlightApp. However, for him the crash is much less frequent than it is for this customer.</li> <li>Other iPad1 testers of the game have never had any trouble. They report that they play the game for hours each day, use their iPad with several other apps in between, and rarely power it down. Similarly, I never had a crash with my iPod Touch 4th gen, which is similar to the iPad1 in the at it has a hi-res screen but only 256k RAM.</li> </ul>
So, it's very mysterious to me what could be so different about these particular users' iPads. It's mysterious that the game works after the device is restarted, but then after some apps have been run the game (sometimes) has trouble loading. My understanding was that if my game demands memory, the OS will auto-close whatever other apps are running, as necessary, to effectively bring the amount of memory back up to the amount that's available on a freshly restarted device. My only conclusion is that after running some apps the device is left in a state where less memory is available because the OS cannot reclaim certain memory blocks or shut down certain apps.
Unfortunately I don't have one of these "misbehaving" devices to develop with. All I can think to do is try to reduce the memory needs of my app by a certain amount, and send it to one of these users who is having trouble and see if it fixes things. That seems like a potentially inefficient approach, however.
Anybody have a better idea?Answer1:
Sounds like the memory spike during texture loading is what's causing the app to be terminated on some devices. It may well use less memory <em>after</em> everything's loaded than it does right near the end of initial loading. This could be explained by things being pushed to virtual memory, whereas direct texture loading could be bombarding the RAM with way too many allocations. My suggestions would be to:<ul><li>Be more aggressive with destroying temporary data structures during loading (
releasea temporary structure the instant all of its useful values have been read/extracted by other things)</li> <li>For
autoreleased objects, keep an
NSAutoreleasePoolaround at all times; you may even want to
alloca pool several times over the course of one method if you use an exceedingly high number of
autoreleased objects.</li> <li>This may sound silly.. intentionally slow down your loading process. If you get rid of parallelized loads (loading multiple objects at once) or possibly insert a manual time delay in your loading thread/methods, this may give the OS more time to push things to virtual memory and thus Watchdog will not detect the app as being a RAM hog.</li> </ul>
<em>EDIT:</em> One possible tactic to implement slower loading: if/when you receive a low memory warning, pause or slow loading down for a few seconds to give other apps time to lower their memory usage, then continue loading at normal speed.
Even if I'm wrong (if
LowMemory...log files show Virtual+Physical usage and thus your app isn't even doing that much), I would suggest then integrating bug reporting such as <a href="http://quincykit.net" rel="nofollow">
QuincyKit</a> so that you get emailed a backtrace and crash description when this bug IS encountered in the wild.