8

Apple defines lev=1 and lev=2 memory warnings as very different (one is "hmm. not much memory around. Be careful", the other is "I am about to kill a process, you have 5 ... 4 ... 3 ...")

...but how do you find out programmatically which one you've received?

I have an iPad app which processes images with specialist tools, and lev=1 memory warnings are inevitable - even processing an image in small pieces, it still uses up a lot of memory just to display all the GUI etc.

I get lev=1 ALL THE TIME and there's literally nothing I can do about it.

lev=2 memory warnings are a very different matter. If I get a lev=2 that usually means that there's some background app taking up a lot of memory, or that something the user has done has bloated memory - and I need to take emergency action to prevent me getting killed. There are things that I can do - but ALL of them are bad for the user (e.g. remove all GUI, wait a couple of seconds, then reload it).

So ... I need two different code paths inside "didRecieveMemoryWarning": one for lev=1 warnings, and one for lev=2 warnings.

EDIT: some info on warning levels: iPhone OS Memory Warnings. What Do The Different Levels Mean?

NB: Apple frequently "doesn't document" things. If we as developers only stuck to the documented information, and the bug-free parts of the API, then many (most?) of the boundary-pushing apps wouldn't exist until several iOS releases later. Instead, we work around the bugs, and we work out what's actually happening where Apple fails to document it.

EDIT2: ...looking into the linked header file, looks like that's got the underlying private function Apple uses to find out which level is current: "OSMemoryNotificationLevel OSMemoryNotificationCurrentLevel(void)" - but I guess there's no way we could get this past Apple Submission :( ?

Community
  • 1
  • 1
Adam
  • 32,900
  • 16
  • 126
  • 153

2 Answers2

6

I don't think the warning level is made available to applications but -- and I know this isn't what you want to hear -- that doesn't really matter. Just because the OS has two different levels of memory warning does not mean that you should do different things at each level and hope that other applications do the Right Thing.

The documentation says:

It is strongly recommended that you implement this method. If your application does not release enough memory during low-memory conditions, the system may terminate it outright.

There is no talk of "be careful" or "about to kill." That may be what currently happens, but is it the same in iOS5? Or in later versions? It's pretty dangerous to make those kinds of assumptions.

I think you need to consider optimising your memory usage. There's almost always a way to optimise images, release cached/intermediate data, more efficiently use autorelease pools, smaller/more efficent data structures. You don't say what techniques you're using currently so it's difficult to be specific.

Stephen Darlington
  • 51,577
  • 12
  • 107
  • 152
  • 2
    Also, you can be pretty sure that if it is a background app that is taking up too much memory, the OS will rather kill the app in the background than yours. – Ole Begemann Sep 28 '11 at 12:24
  • "That may be what currently happens, but is it the same in iOS5? Or in later versions? It's pretty dangerous to make those kinds of assumptions." - unhelpful. This *IS* what happens. It's irrelevant what iOS 5 does or doesn't do - it is GUARANTEED to suck right now. I want it to "not suck". If it works OK now, and works poorly with iOS 5 that will be better than the alternative - works badly with everything! – Adam Sep 28 '11 at 17:44
  • 1
    "I think you need to consider optimising your memory usage." - if there's something wrong with the question, please point it out. I tried to be clear on this: there is no place where the memory could be reduced - it's literally impossible: everything that's being rendered MUST be rendered. Everything is carefully memory-managed already, and only loaded if needed - in small pieces, no less. The only option is to blank the screen, and stop the app. To put this into context, we're working on 2 gigabytes of source data, in realtime. No matter what you do, the memory is needed. – Adam Sep 28 '11 at 17:48
  • To be more explicit: all images are optimized OpenGL textures. There is no intermediate data. There is almost zero object allocation. The data structures are all C-level structs. We have already done substantial packing / RLE to reduce memory down to the level where the app would run at all. – Adam Sep 28 '11 at 17:49
  • @ Ole Begemann - I see SpringBoard issuing kill signals to the background apps - but they don't die. Or if they do, they get re-launched in the background. Mail is an obvious culprit, and I can believe it's using an Apple private method to refuse to die. For other apps - e.g. Skype, which seems to just bounce straight back at high memory usage - is this something I need to change in the app? Or is Skype doing something evil to keep itself alive, even in the background? – Adam Sep 28 '11 at 17:52
  • 1
    I'm not sure what you want people to say. The OS says you're using too much memory but you say you need it all. Only one of those two are going to win that battle and it's not you. You're not going to stop Mail running; you're going to find people running Skype; you're going to find people who have jailbroken their handsets and have virtually no memory spare. Maybe you need a "degraded" mode that shows fewer graphics on machines with less memory? I don't know. But I do know that "tricking" iOS in the manner you suggest would not work out well. – Stephen Darlington Sep 29 '11 at 09:16
  • Exhibit A: Real Racing 2 HD. Beautiful graphics, great sound effect, nice controls, Game Center, fun to play. But I don't use it. It crashes _all the time_. If I wasn't running a beta OS I would give it a really poor review in iTunes. Pushing the state of the art is fantastic, but it has to work for most people. – Stephen Darlington Sep 29 '11 at 09:19
  • @StephenDarlington - "degraded mode" is essentially the aim, yes, but since Apple won't allow us to query "actual free memory", we're back to square one: how to decide when to do that? In the end, we shipped something that stays in mem limits - barely - on iPad1 if you are ONLY running Mail OR Skype, and we accepted the inevitable few crashes. In 4 weeks, we've only had a single crash report - and that was apparently due to .... Skype (no surprise :)). – Adam Nov 24 '11 at 12:50
  • 1
    Incidentally, the core problem here - arguably - is that Skype and Mail are pathological apps that break iOS's multi-tasking (arguably not their fault - they're following Apple's spec). Both of them DO NOT leave RAM when they go to the background - I believe this is a flaw in Apple's background code for network connections: because both apps request "keep my network connections running", they get force-stay-in-RAM ... So, ideally: Apple would change the OS implementation ... and/or: Apple would put stricter restrictions on that flag requesting to keep net connections running. Tricky problem! – Adam Nov 24 '11 at 12:52
0

An alternative approach that I have NOT TRIED but might work: Capture the output of Apple's system logger (ASL), look for the lev2 warning string.

Assuming Apple is actually using the ASL (which they might not be!) you could try following the instructions here: http://www.cocoanetics.com/2011/03/accessing-the-ios-system-log/ - which show how to access the ASL using Apple public API's.

Adam
  • 32,900
  • 16
  • 126
  • 153