Avisos de memória do iPhone OS. O que significam os diferentes níveis?

85

Em relação à arte negra de gerenciar memória em dispositivos iPhone OS: o que significam os diferentes níveis de aviso de memória. Nível 1? Nível 2? O dial vai para 11?

Contexto: Depois de um extenso período de teste de estresse de memória - incluindo a execução do meu aplicativo para iPad com o aplicativo reprodutor de música do iPod em execução, estou inclinado a ignorar os avisos de memória aleatórios, mas raros, que estou recebendo. Meu aplicativo nunca falha. Sempre. Meu aplicativo está livre de vazamentos. E, bem, os avisos dos memes simplesmente não parecem importar.

Obrigada
doug

dugla
fonte

Respostas:

98

Basicamente, os avisos significam que o dispositivo está com pouca memória e que, "Se você pudesse liberar um pouco de memória que não está usando ativamente, seria ótimo! ". Se o gerenciamento de sua memória for restrito e você não tiver objetos que possam ser praticamente descartados, apenas passe a mensagem adiante e ignore-a.

Williham Totland
fonte
25
LOL "Se você pudesse, por favor, liberar alguma memória que não está usando ativamente, seria ótimo!" Inestimável ;-) Saúde
dugla
15
Você parece um veterano mal-humorado da dança da memória maluca do iPhone OS.
dugla
193

Avisos de nível de memória são registrados por SpringBoard. Como desenvolvedor de aplicativos, você não precisa se preocupar com isso. Basta responder a -{application}didReceiveMemoryWarningisso.


Existem 4 níveis de avisos (0 a 3). Eles são definidos no observador de memória do kernel e podem ser obtidos pela função não tão públicaOSMemoryNotificationCurrentLevel() .

typedef enum {
    OSMemoryNotificationLevelAny      = -1,
    OSMemoryNotificationLevelNormal   =  0,
    OSMemoryNotificationLevelWarning  =  1,
    OSMemoryNotificationLevelUrgent   =  2,
    OSMemoryNotificationLevelCritical =  3
} OSMemoryNotificationLevel;

O modo como os níveis são acionados não é documentado. SpringBoard é configurado para fazer o seguinte em cada nível de memória:

  1. Aviso (não normal) - Reiniciar ou atrasar a reinicialização automática de aplicativos não essenciais em segundo plano, por exemplo, Mail.
  2. Urgente - feche todos os aplicativos de fundo, por exemplo, Safari e iPod.
  3. Crítico e além - O kernel assumirá o controle, provavelmente matando SpringBoard ou mesmo reiniciando.

Matar o aplicativo ativo (jetsam) não é feito pelo SpringBoard, mas launchd.

Kennytm
fonte
Obrigado por isso. Foi uma disputa entre você e Williham, o comediante, nessa questão. O humor vence. Felicidades.
dugla
Oi, eu tenho o mesmo problema. Depois de executar o aplicativo continuamente por mais de 5 vezes, estou recebendo um aviso de memória recebida. Nível = 1 por 20 vezes, mas o aplicativo não está travando. Mas quando recebo esta mensagem, Aviso de memória recebido. Nível = 2 meu aplicativo está travando. O Nível 2 está aparecendo após o Nível 1 aparecendo por quase 20 vezes. Como posso fazer meu aplicativo não travar. Obrigado
srikanth rongali
1
@Kenny: Menos memória significa, quanto podemos usar no máximo. Quanto podemos ter bytes ativos. No meu registro de travamento, eu tenho isso. Páginas gratuitas: 371 Páginas com fio: 12192 Páginas purgáveis: 0 Maior processo: DTMobileIS O que isso significa? Onde devo cuidar? Obrigado.
srikanth rongali
9
@srik: É melhor você fazer uma nova pergunta .
kennytm
@kennytm: isso ainda é possível com ios8? Eu vi que a função é definida em libsystem_c.dylib. Seria ótimo se eu pudesse usar isso. Obrigado
focs
12

De OSMemoryNotification.h ,

/*
** Threshold values for notifications
*/

typedef enum {
    OSMemoryNotificationLevelAny      = -1,
    OSMemoryNotificationLevelNormal   =  0,
    OSMemoryNotificationLevelWarning  =  1,
    OSMemoryNotificationLevelUrgent   =  2,
    OSMemoryNotificationLevelCritical =  3
} OSMemoryNotificationLevel;

total 5 níveis de aviso de memória (-1,3).

Com relação à descrição do aviso de nível de memória, a resposta de @ KennyTM é excelente.

Quero adicionar vários pontos relacionados que podem ajudar o PM e outros.


O que você deve fazer ao receber um aviso de nível de memória?

Ao receber qualquer um desses avisos, o método do manipulador deve responder liberando imediatamente qualquer memória desnecessária. Por exemplo, o comportamento padrão da classe UIViewController é limpar sua visualização se essa visualização não estiver visível no momento; as subclasses podem complementar o comportamento padrão eliminando estruturas de dados adicionais. Um aplicativo que mantém um cache de imagens pode responder liberando quaisquer imagens que não estejam atualmente na tela.


Como observar o aviso de nível de memória?

De http://developer.apple.com/library/ios/#documentation/iphone/conceptual/iphoneosprogrammingguide/PerformanceTuning/PerformanceTuning.html

Quando o sistema enviar um aviso de pouca memória para o seu aplicativo, responda imediatamente. O iOS notifica todos os aplicativos em execução sempre que a quantidade de memória livre cai abaixo de um limite seguro. (Ele não notifica aplicativos suspensos.) Se seu aplicativo receber esse aviso, ele deve liberar o máximo de memória possível. A melhor maneira de fazer isso é remover referências fortes a caches, objetos de imagem e outros objetos de dados que podem ser recriados posteriormente.

O UIKit fornece várias maneiras de receber avisos de pouca memória, incluindo o seguinte:

  • Implemente o método applicationDidReceiveMemoryWarning: do delegado do seu aplicativo.
  • Substitua o método didReceiveMemoryWarning em sua subclasse UIViewController customizada.
  • Registre-se para receber a notificação UIApplicationDidReceiveMemoryWarningNotification.

Como reduzir a pegada de memória do seu aplicativo?

  • Elimine vazamentos de memória.
  • Torne os arquivos de recursos os menores possíveis.
  • Use Core Data ou SQLite para grandes conjuntos de dados.
  • Carregue recursos preguiçosamente.
  • Construa seu programa usando a opção Thumb.

Detalhes em http://developer.apple.com/library/ios/#documentation/iphone/conceptual/iphoneosprogrammingguide/PerformanceTuning/PerformanceTuning.html


Como alocar memória com sabedoria?

  • Reduza o uso de objetos liberados automaticamente: Com a contagem automática de referência (ARC), é melhor alocar / init objetos e deixar o compilador liberá-los para você no momento apropriado. Isso é verdadeiro até mesmo para objetos temporários que no passado você poderia ter liberado automaticamente para evitar que sobrevivam ao escopo do método atual.
  • Imponha limites de tamanho aos recursos : evite carregar um arquivo de recurso grande quando um menor for suficiente. Em vez de usar uma imagem de alta resolução, use uma que seja de tamanho adequado para dispositivos baseados em iOS. Se você deve usar arquivos de recursos grandes, encontre maneiras de carregar apenas a parte do arquivo necessária em um determinado momento. Por exemplo, em vez de carregar o arquivo inteiro na memória, use as funções mmap e munmap para mapear partes do arquivo para dentro e para fora da memória. Para obter mais informações sobre o mapeamento de arquivos na memória.
  • Evite conjuntos de problemas ilimitados : Os conjuntos de problemas ilimitados podem exigir uma quantidade arbitrariamente grande de dados para serem computados. Se o conjunto exigir mais memória do que está disponível, seu aplicativo pode não conseguir concluir os cálculos. Seus aplicativos devem evitar esses conjuntos sempre que possível e resolver problemas com limites de memória conhecidos.
Md Mahbubur Rahman
fonte