Como você detecta programaticamente o tamanho de heap do aplicativo disponível para um aplicativo Android?
Ouvi dizer que há uma função que faz isso em versões posteriores do SDK. De qualquer forma, estou procurando uma solução que funcione para a versão 1.5 ou superior.
android
memory
heap
heap-memory
hpique
fonte
fonte
Respostas:
Há duas maneiras de pensar sobre sua frase "tamanho de heap do aplicativo disponível":
Quanto heap meu aplicativo pode usar antes que um erro grave seja acionado? E
Quanto heap meu aplicativo deve usar, dadas as restrições da versão do sistema operacional Android e o hardware do dispositivo do usuário?
Existe um método diferente para determinar cada uma das opções acima.
Para o item 1 acima:
maxMemory()
que pode ser invocado (por exemplo, no
onCreate()
método da sua atividade principal ) da seguinte maneira:Este método informa quantos bytes totais de heap seu aplicativo tem permissão para usar.
Para o item 2 acima:
getMemoryClass()
que pode ser chamado da seguinte maneira:
Esse método informa aproximadamente quantos megabytes de heap seu aplicativo deve usar se quiser respeitar adequadamente os limites do dispositivo atual e os direitos de outros aplicativos de serem executados sem serem repetidamente forçados ao ciclo
onStop()
/onResume()
, pois são rudes. fica sem memória enquanto o aplicativo elefantino toma banho no jacuzzi Android.Essa distinção não está claramente documentada, até onde eu sei, mas testei essa hipótese em cinco dispositivos Android diferentes (veja abaixo) e confirmei, para minha satisfação, que esta é uma interpretação correta.
Para uma versão padrão do Android,
maxMemory()
normalmente retornará aproximadamente o mesmo número de megabytes indicado emgetMemoryClass()
(isto é, aproximadamente um milhão de vezes o último valor).A única situação (da qual eu sei) para a qual os dois métodos podem divergir é em um dispositivo raiz executando uma versão Android como o CyanogenMod, que permite ao usuário selecionar manualmente o tamanho de heap permitido para cada aplicativo. No CM, por exemplo, esta opção aparece em "Configurações do CyanogenMod" / "Desempenho" / "Tamanho da pilha da VM".
NOTA: Esteja ciente de que a configuração manual desse valor pode prejudicar o sistema, especialmente se você selecionar um valor menor que o normal para o seu dispositivo.
Aqui estão meus resultados de teste, mostrando os valores retornados por
maxMemory()
egetMemoryClass()
para quatro dispositivos diferentes executando o CyanogenMod, usando dois valores de heap diferentes (definidos manualmente) para cada um:Além do exposto, testei em um tablet Novo7 Paladin com Ice Cream Sandwich. Essa era essencialmente uma versão de estoque do ICS, exceto que eu enraizei o tablet através de um processo simples que não substitui todo o sistema operacional e, em particular, não fornece uma interface que permita que o tamanho do heap seja ajustado manualmente.
Para esse dispositivo, aqui estão os resultados:
Também (por Kishore em um comentário abaixo):
E (pelo comentário de akauppi):
Por um comentário de cmcromance:
E (comentários de tencent):
Outros dispositivos
Não testei esses dois métodos usando a opção especial manifest: android: largeHeap = "true" disponível desde o Honeycomb, mas, graças ao cmcromance e ao tencent, temos alguns exemplos de valores largeHeap, conforme relatado acima.
Minha expectativa (que parece ser suportada pelos números grandes do heap acima) seria que essa opção tivesse um efeito semelhante à configuração manual do heap por meio de um sistema operacional raiz - ou seja, aumentaria o valor
maxMemory()
ao sairgetMemoryClass()
sozinho. Há outro método, getLargeMemoryClass (), que indica quanta memória é permitida para um aplicativo usando a configuração largeHeap. A documentação para getLargeMemoryClass () afirma: "a maioria dos aplicativos não precisa dessa quantidade de memória e deve permanecer com o limite de getMemoryClass ()".Se eu adivinhei corretamente, usar essa opção teria os mesmos benefícios (e perigos) que o espaço disponibilizado por um usuário que aumentou a pilha por meio de um sistema operacional raiz (por exemplo, se o aplicativo usar memória adicional, provavelmente não funcionará tão bem com outros aplicativos que o usuário esteja executando ao mesmo tempo).
Observe que a classe de memória aparentemente não precisa ter um múltiplo de 8 MB.
Podemos ver, acima, que o
getMemoryClass()
resultado é imutável para uma determinada configuração de dispositivo / SO, enquanto o valor maxMemory () muda quando o heap é definido de forma diferente pelo usuário.Minha própria experiência prática é que, no G1 (que tem uma classe de memória de 16), se eu selecionar manualmente 24 MB como o tamanho da pilha, posso executar sem erros, mesmo quando meu uso de memória puder subir para 20 MB (presumivelmente chegam a 24 MB, embora eu não tenha tentado isso). Mas outros aplicativos igualmente grandes podem ser lavados da memória como resultado da porcaria do meu próprio aplicativo. E, por outro lado, meu aplicativo pode ficar sem memória se esses outros aplicativos de alta manutenção forem trazidos ao primeiro plano pelo usuário.
Portanto, você não pode exceder a quantidade de memória especificada por
maxMemory()
. E, você deve tentar permanecer dentro dos limites especificados porgetMemoryClass()
. Uma maneira de fazer isso, se tudo mais falhar, pode ser limitar a funcionalidade desses dispositivos de maneira a economizar memória.Por fim, se você planeja ultrapassar o número de megabytes especificado em
getMemoryClass()
, meu conselho é trabalhar arduamente para salvar e restaurar o estado do aplicativo, para que a experiência do usuário seja praticamente ininterrupta se ocorrer umonStop()
/onResume()
ciclo.No meu caso, por motivos de desempenho, estou limitando meu aplicativo a dispositivos com a versão 2.2 e superior, e isso significa que quase todos os dispositivos que executam meu aplicativo terão uma memoryClass de 24 ou superior. Para que eu possa projetar para ocupar até 20 MB de heap e me sentir bastante confiante de que meu aplicativo funcionará bem com os outros aplicativos que o usuário possa estar executando ao mesmo tempo.
Mas sempre haverá alguns usuários enraizados que carregaram uma versão 2.2 ou superior do Android em um dispositivo mais antigo (por exemplo, um G1). Quando você encontra essa configuração, o ideal é reduzir o uso de memória, mesmo que
maxMemory()
esteja lhe dizendo que você pode ir muito mais alto do que os 16 MB quegetMemoryClass()
estão lhe dizendo que você deveria estar alvejando. E se você não pode garantir com segurança que a sua aplicação vai viver dentro desse orçamento, em seguida, pelo menos, fazer-se de queonStop()
/onResume()
funciona perfeitamente.getMemoryClass()
, como indicado por Diane Hackborn (hackbod) acima, só está disponível no nível 5 da API (Android 2.0) e, como aconselha, você pode assumir que o hardware físico de qualquer dispositivo executando uma versão anterior do sistema operacional foi projetado para oferecer suporte ideal a aplicativos que ocupam um espaço de heap não superior a 16 MB.Por outro lado,
maxMemory()
de acordo com a documentação, está disponível todo o caminho de volta ao nível API 1.maxMemory()
, em uma pré-versão 2.0, provavelmente irá retornar um valor de 16 MB, mas eu fazer ver que em meus (muito mais tarde) versões CyanogenMod do usuário pode selecionar um valor de heap tão baixo quanto 12MB, o que presumivelmente resultaria em um limite de heap mais baixo e, portanto, sugiro que você continue testando omaxMemory()
valor, mesmo para versões do sistema operacional anteriores à 2.0. Você pode até se recusar a executar no caso improvável de que esse valor seja definido ainda mais baixo que 16 MB, se você precisar ter mais do que omaxMemory()
indicado é permitido.fonte
A API oficial é:
fonte
Debug.getNativeHeapSize()
vai fazer o truque, eu acho. Está presente desde a versão 1.0, no entanto.A
Debug
classe possui muitos métodos excelentes para rastrear alocações e outras preocupações com o desempenho. Além disso, se você precisar detectar uma situação de pouca memória, verifiqueActivity.onLowMemory()
.fonte
Aqui está como você faz isso:
Obtendo o tamanho máximo de heap que o aplicativo pode usar:
Obtendo quanto da pilha seu aplicativo usa atualmente:
Obtendo quanto da pilha seu aplicativo agora pode usar (memória disponível):
E, para formatar bem cada um deles, você pode usar:
fonte
Isso retorna o tamanho máximo da pilha em bytes:
Eu estava usando ActivityManager.getMemoryClass (), mas no CyanogenMod 7 (não testei em outro lugar) ele retornará um valor errado se o usuário definir o tamanho da pilha manualmente.
fonte
getMemoryClass
parece indicar que o número pode não ser o mesmo que o tamanho de heap disponível para sua vm, e como o documentogetNativeHeapSize
é ... taciturno, eu realmente acho queRuntime.getRuntime().maxMemory()
é a melhor resposta.Algumas operações são mais rápidas que o gerenciador de espaço heap java. Atrasar as operações por algum tempo pode liberar espaço na memória. Você pode usar este método para escapar do erro de tamanho de heap:
fonte
AvailableMemoryPercentage
está de acordo com a fórmula: quanto de memória do dispositivo está atualmente livre.MIN_AVAILABLE_MEMORY_PERCENTAGE
é seu parâmetro customizado, um limite no qual você começa a aguardar que o coletor de lixo faça seu trabalho.Asus Nexus 7 (2013) 32Gig: getMemoryClass () = 192 maxMemory () = 201326592
Cometi o erro de criar um protótipo do meu jogo no Nexus 7 e depois descobrir que ele ficou sem memória quase imediatamente no tablet genérico 4.04 da minha esposa (memoryclass 48, maxmemory 50331648)
Precisarei reestruturar meu projeto para carregar menos recursos quando determinar que a classe de memória está baixa.
Existe uma maneira em Java para ver o tamanho atual da pilha? (Eu posso ver isso claramente no logCat durante a depuração, mas eu gostaria de uma maneira de vê-lo no código para se adaptar, como se o currentheap> (maxmemory / 2) descarregasse bitmaps de alta qualidade e carregasse baixa qualidade
fonte
Você quer dizer programaticamente ou apenas enquanto está desenvolvendo e depurando? Nesse último caso, é possível ver essas informações da perspectiva DDMS no Eclipse. Quando o emulador (possivelmente o telefone físico conectado) estiver em execução, ele listará os processos ativos em uma janela à esquerda. Você pode selecioná-lo e há uma opção para rastrear as alocações de heap.
fonte
o valor é b
o valor é MB
fonte
rt
? Onde é declarado?