orçamento máximo de memória do aplicativo ios


152

Estou trabalhando em um jogo ios que tem como alvo, no mínimo, os 3gs. Estamos usando recursos HD para dispositivos de exibição de retina (iphone 4, ipod touch 4th gen).

Em termos de memória, o Ipod Touch de 4ª geração parece ser o dispositivo mais restritivo para nós, uma vez que possui a mesma quantidade de RAM (256 em comparação com o 512 do Iphone 4) que 3gs, mas estamos usando recursos de HD nele. O aplicativo costumava travar ao tentar carregar 100-110mb de ram, mas agora que reduzimos para 70 MB, nunca tivemos o carregamento travado.

Depois de muita pesquisa, parece não haver um limite oficial oficial; então, como devemos saber qual orçamento de memória usar para ser seguro? Queremos poder fornecer aos artistas um orçamento que eles possam usar sem preocupações de memória para cada mapa.


1
Possível duplicação da alocação de memória
Nhgrif 30/11/2015

14
Não tenho certeza de como essa pergunta pode ser uma duplicata de algo que foi feito posteriormente.
Jasper

Respostas:


42

Acho que você respondeu à sua própria pergunta: tente não exceder o limite de 70 Mb, no entanto, depende realmente de muitas coisas: qual versão do iOS você está usando (não SDK), quantos aplicativos sendo executados em segundo plano, que memória exata você está usando etc.

Apenas evite os salpicos de memória instantânea (por exemplo, você está usando 40 Mb de RAM e alocando mais 80 Mb para um cálculo curto). Nesse caso, o iOS mataria seu aplicativo imediatamente.

Você também deve considerar o carregamento lento de ativos (carregue-os somente quando realmente precisar e não antes).


2
Só que queríamos colocar o máximo de coisas possível (gráficos e sons). Os artistas sempre querem colocar o máximo que puderem em um jogo, por isso quero limitá-los com um orçamento. Eu acho que teremos que testar em muitos dispositivos diferentes em configurações diferentes para encontrar uma pegada de memória máxima razoável para usar.
Frilla

2
A alocação de apenas 70 MB (o que provavelmente está abaixo do orçamento) a qualquer momento no dispositivo (mesmo após o uso intenso em outros aplicativos que exigem muita memória) sempre garantirá uma alocação bem-sucedida, ou potencialmente ainda trava?
Steven Lu

1
@Steven Lu depende do seu dispositivo. Por exemplo, nos mais novos, como a alocação de 70 Mb para iPhone5 ou iPad4, não é um problema.
Max

1
sim, mas quero saber se posso garantir que, desde que eu mantenha o uso total do meu aplicativo no orçamento de memória específico do dispositivo mágico, ele não será encerrado!
Steven Lu

1
não há garantias
Max

421

Resultados dos testes com o utilitário Split escreveu (o link está em sua resposta):

dispositivo: (quantidade de falha / quantidade total / porcentagem do total)

  • iPad1: 127MB / 256MB / 49%
  • iPad2: 275MB / 512MB / 53%
  • iPad3: 645MB / 1024MB / 62%
  • iPad4: 585MB / 1024MB / 57% (iOS 8.1)
  • iPad Mini de 1ª geração: 297MB / 512MB / 58%
  • iPad Mini retina: 696MB / 1024MB / 68% (iOS 7.1)
  • iPad Air: 697MB / 1024MB / 68%
  • iPad Air 2: 1383MB / 2048MB / 68% (iOS 10.2.1)
  • iPad Pro 9.7 ": 1395MB / 1971MB / 71% (iOS 10.0.2 (14A456))
  • iPad Pro 10.5 ”: 3057/4000/76% (iOS 11 beta4)
  • iPad Pro 12.9 ”(2015): 3058/3999/76% (iOS 11.2.1)
  • iPad Pro 12.9 ”(2017): 3057/3974/77% (iOS 11 beta4)
  • iPad Pro 11.0 ”(2018): 2858/3769/76% (iOS 12.1)
  • iPad Pro 12.9 "(2018, 1 TB): 4598/5650/81% (iOS 12.1)
  • iPad 10.2: 1844/2998/62% (iOS 13.2.3)
  • iPod touch de quarta geração: 130MB / 256MB / 51% (iOS 6.1.1)
  • iPod touch 5ª geração: 286MB / 512MB / 56% (iOS 7.0)
  • iPhone4: 325MB / 512MB / 63%
  • iPhone4s: 286MB / 512MB / 56%
  • iPhone5: 645MB / 1024MB / 62%
  • iPhone5s: 646MB / 1024MB / 63%
  • iPhone6: 645MB / 1024MB / 62% (iOS 8.x)
  • iPhone6 ​​+: 645MB / 1024MB / 62% (iOS 8.x)
  • iPhone6s: 1396MB / 2048MB / 68% (iOS 9.2)
  • iPhone6s +: 1392MB / 2048MB / 68% (iOS 10.2.1)
  • iPhoneSE: 1395MB / 2048MB / 69% (iOS 9.3)
  • iPhone7: 1395/2048 MB / 68% (iOS 10.2)
  • iPhone7 +: 2040MB / 3072MB / 66% (iOS 10.2.1)
  • iPhone8: 1364 / 1990MB / 70% (iOS 12.1)
  • iPhone X: 1392/2785/50% (iOS 11.2.1)
  • iPhone XS: 2040/3754/54% (iOS 12.1)
  • iPhone XS Max: 2039/3735/55% (iOS 12.1)
  • iPhone XR: 1792/2813 / 63% (iOS 12.1)
  • iPhone 11: 2068/3844/54% (iOS 13.1.3)
  • iPhone 11 Pro Max: 2067/3740/55% (iOS 13.2.3)

2
iPhone4: valor semelhante confirmado, parece legítimo: P
cprcrack 30/10/2013

3
O iPhone 5 trava a ± 645 MB.
asp_net

4
@ JasperPol Editei sua postagem para incluir vários dispositivos que tenho, espero que esteja tudo bem. Adicionei a versão para iOS em que testei, caso isso importe, mas fique à vontade para removê-la se achar que não é importante.
Josephh

2
Impressionante que esta lista tenha sido criada e mantida. Na minha experiência, tive que manter a memória muito mais baixa para estar segura, talvez 20% do que é mostrado aqui. As diferenças de dispositivo para dispositivo também são altamente variáveis.
user1021430

1
Acabei de executar isso em um iPad Pro 12.9. Aviso de memória em 2451MB, falha em 3064MB, total de 3981MB.
bloqueia

134

Criei um pequeno utilitário que tenta alocar o máximo de memória possível para travar e registra quando ocorrem avisos e travamentos de memória. Isso ajuda a descobrir qual é o orçamento de memória para qualquer dispositivo iOS.

https://github.com/Split82/iOSMemoryBudgetTest


Fiz um teste interessante: executei meu aplicativo com o uso da memória de monitoramento do xcode, entrou em segundo plano, executou o BudgetTest. O teste foi encerrado enquanto meu aplicativo em segundo plano não. Estou interessado em saber o porquê. Além disso, isso vai contra o que o @cprcrack disse na outra resposta.
Roberto

19

No meu aplicativo, a experiência do usuário é melhor se mais memória for usada, por isso tenho que decidir se realmente devo liberar toda a memória possível didReceiveMemoryWarning. Com base na resposta de Split e Jasper Pol, usar um máximo de 45% da memória total do dispositivo parece ser um limite seguro (obrigado pessoal).

Caso alguém queira ver minha implementação real:

#import "mach/mach.h"

- (void)didReceiveMemoryWarning
{
    // Remember to call super
    [super didReceiveMemoryWarning];

    // If we are using more than 45% of the memory, free even important resources,
    // because the app might be killed by the OS if we don't
    if ([self __getMemoryUsedPer1] > 0.45)
    {
        // Free important resources here
    }

    // Free regular unimportant resources always here
}

- (float)__getMemoryUsedPer1
{
    struct mach_task_basic_info info;
    mach_msg_type_number_t size = sizeof(info);
    kern_return_t kerr = task_info(mach_task_self(), MACH_TASK_BASIC_INFO, (task_info_t)&info, &size);
    if (kerr == KERN_SUCCESS)
    {
        float used_bytes = info.resident_size;
        float total_bytes = [NSProcessInfo processInfo].physicalMemory;
        //NSLog(@"Used: %f MB out of %f MB (%f%%)", used_bytes / 1024.0f / 1024.0f, total_bytes / 1024.0f / 1024.0f, used_bytes * 100.0f / total_bytes);
        return used_bytes / total_bytes;
    }
    return 1;
}

Swift (com base nesta resposta ):

func __getMemoryUsedPer1() -> Float
{
    let MACH_TASK_BASIC_INFO_COUNT = (sizeof(mach_task_basic_info_data_t) / sizeof(natural_t))
    let name = mach_task_self_
    let flavor = task_flavor_t(MACH_TASK_BASIC_INFO)
    var size = mach_msg_type_number_t(MACH_TASK_BASIC_INFO_COUNT)
    var infoPointer = UnsafeMutablePointer<mach_task_basic_info>.alloc(1)
    let kerr = task_info(name, flavor, UnsafeMutablePointer(infoPointer), &size)
    let info = infoPointer.move()
    infoPointer.dealloc(1)
    if kerr == KERN_SUCCESS
    {
        var used_bytes: Float = Float(info.resident_size)
        var total_bytes: Float = Float(NSProcessInfo.processInfo().physicalMemory)
        println("Used: \(used_bytes / 1024.0 / 1024.0) MB out of \(total_bytes / 1024.0 / 1024.0) MB (\(used_bytes * 100.0 / total_bytes)%%)")
        return used_bytes / total_bytes
    }
    return 1
}

1
tamanho deve ser TASK_BASIC_INFO_COUNT vez de sizeof (info) - este erro para muitos lugares com o mesmo código colado cópia
Maxim Kholyavkin

Obrigado Speakus. Você parece estar certo com base neste link . Você tem alguma outra referência onde essas informações podem ser encontradas?
amigos estão dizendo sobre cprcrack

Apple usa TASK_BASIC_INFO_COUNT também
Maxim Kholyavkin

45% não é mais um limite seguro, é muito próximo ao valor de falha de 50% para o iPhone X. Sugiro usar 40% ou valor separado para cada dispositivo.
Slyv

8

Ao bifurcar o repo do SPLITS, criei um para testar a memória do iOS que pode ser alocada para a Extensão de hoje

iOSMemoryBudgetTestForExtension

A seguir, o resultado que obtive no iPhone 5s

Aviso de memória em 10 MB

App travou em 12 MB

Dessa forma, a Apple está apenas permitindo que quaisquer extensões funcionem com todo o seu potencial .


7

Você deve assistir à sessão 147 dos vídeos da sessão da WWDC 2010 . É "Otimização avançada de desempenho no iPhone OS, parte 2".
Há muitos bons conselhos sobre otimizações de memória.

Algumas das dicas são:

  • Use NSAutoReleasePools aninhados para garantir que o uso da memória não acelere.
  • Use CGImageSourceao criar miniaturas a partir de imagens grandes.
  • Responda a avisos de pouca memória.

Minha pergunta não é sobre como otimizar (obrigado pelo link), é sobre quanto podemos nos permitir usar. O motivo é que, por exemplo, se otimizarmos para ganhar 20mb, os artistas desejarão usá-lo se estiver dentro do "orçamento" razoável, com certeza de que isso não causará problemas de desempenho ou falha de memória.
Frilla

ESTÁ BEM. A falha ocorrerá porque o sistema operacional está encerrando o aplicativo devido a memória restrita. Você poderia apenas adicionar um NSLogpara dentro didReceiveMemoryWarninge, em seguida, fazer alguns testes onde alocar diferentes quantidades de memória e depois ver quando os avisos de memória começar a chutar.
Kobski

4

A partir do iOS13, existe uma maneira suportada pela Apple de consultar isso usando

#include <os/proc.h>

size_t os_proc_available_memory(void)

Introduzido aqui: https://developer.apple.com/videos/play/wwdc2019/606/

Cerca de min 29-ish.

Editar: Adicionando link à documentação https://developer.apple.com/documentation/os/3191911-os_proc_available_memory?language=objc


Finalmente! Testei os_proc_available_memory () em alguns dispositivos, e os resultados são muito semelhantes aos valores da grande tabela acima!
Slyv 24/01

3
- (float)__getMemoryUsedPer1
{
    struct mach_task_basic_info info;
    mach_msg_type_number_t size = MACH_TASK_BASIC_INFO;
    kern_return_t kerr = task_info(mach_task_self(), MACH_TASK_BASIC_INFO, (task_info_t)&info, &size);
    if (kerr == KERN_SUCCESS)
    {
        float used_bytes = info.resident_size;
        float total_bytes = [NSProcessInfo processInfo].physicalMemory;
        //NSLog(@"Used: %f MB out of %f MB (%f%%)", used_bytes / 1024.0f / 1024.0f, total_bytes / 1024.0f / 1024.0f, used_bytes * 100.0f / total_bytes);
        return used_bytes / total_bytes;
    }
    return 1;
}

Se alguém usar TASK_BASIC_INFO_COUNT em vez de MACH_TASK_BASIC_INFO, você receberá

kerr == KERN_INVALID_ARGUMENT (4)


Você deve pelo menos mencionar que sua resposta é quase uma cópia e colagem exata do @ cprcrack's acima. A única diferença é TASK_BASIC_INFO_COUNT.
mrvincenzo 25/02

2

Criei mais uma lista classificando a lista do Jaspers por RAM do dispositivo (fiz meus próprios testes com a ferramenta Split e corrigi alguns resultados - verifique meus comentários no thread do Jaspers).

RAM do dispositivo: intervalo percentual para travar

  • 256MB: 49% - 51%
  • 512MB: 53% - 63%
  • 1024MB: 57% - 68%
  • 2048MB: 68% - 69%
  • 3072MB: 63% - 66%
  • 4096MB: 77%
  • 6144MB: 81%

Casos especiais:

  • iPhone X (3072MB): 50%
  • iPhone XS / XS Max (4096MB): 55%
  • iPhone XR (3072MB): 63%
  • iPhone 11/11 Pro Max (4096MB): 54% - 55%

A RAM do dispositivo pode ser lida facilmente:

[NSProcessInfo processInfo].physicalMemory

Pela minha experiência, é seguro usar 45% para dispositivos de 1 GB, 50% para dispositivos de 2/3 GB e 55% para dispositivos de 4 GB. A porcentagem do macOS pode ser um pouco maior.


atualização: parece que o iPhone X é uma exceção - trava quando 50% da RAM é usada (testada com o aplicativo iOSMemoryBudgetTest). Eu atualizei a lista.
Slyv

0

Trabalhando com as muitas respostas acima, implementei o novo método os_proc_available_memory()da Apple para o iOS 13+, juntamente com o NSByteCountFormatterqual oferece várias opções de formatação úteis para obter uma saída melhor da memória:

#include <os/proc.h>

....

- (NSString *)memoryStringForBytes:(unsigned long long)memoryBytes {
    NSByteCountFormatter *byteFormatter = [[NSByteCountFormatter alloc] init];
    byteFormatter.allowedUnits = NSByteCountFormatterUseGB;
    byteFormatter.countStyle = NSByteCountFormatterCountStyleMemory;
    NSString *memoryString = [byteFormatter stringFromByteCount:memoryBytes];
    return memoryString;
}

- (void)memoryLoggingOutput {
    if (@available(iOS 13.0, *)) {
        NSLog(@"Physical memory available: %@", [self memoryStringForBytes:[NSProcessInfo processInfo].physicalMemory]);
        NSLog(@"Memory A (brackets): %@", [self memoryStringForBytes:(long)os_proc_available_memory()]);
        NSLog(@"Memory B (no brackets): %@", [self memoryStringForBytes:(long)os_proc_available_memory]);
    }
}

Nota importante: Não esqueça o ()no final. Eu incluí as duas NSLogopções no memoryLoggingOutputmétodo porque ele não avisa que elas estão ausentes e a falha em incluir os colchetes retorna um resultado inesperado, mas constante.

A cadeia retornada do método memoryStringForBytesgera valores da seguinte forma:

NSLog(@"%@", [self memoryStringForBytes:(long)os_proc_available_memory()]); // 1.93 GB
// 2 seconds later
NSLog(@"%@", [self memoryStringForBytes:(long)os_proc_available_memory()]); // 1.84 GB
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.