Como posso encontrar a memória usada no meu aplicativo Android programaticamente?
Espero que haja uma maneira de fazer isso. Além disso, como obtenho também a memória livre do telefone?
java
android
memory
memory-management
Andrea Baccega
fonte
fonte
Respostas:
Observe que o uso de memória em sistemas operacionais modernos como o Linux é uma área extremamente complicada e difícil de entender. De fato, as chances de você realmente interpretar corretamente quaisquer números que conseguir são extremamente baixas. (Praticamente toda vez que olho para os números de uso de memória com outros engenheiros, sempre há uma longa discussão sobre o que eles realmente significam que só resultam em uma vaga conclusão.)
Nota: agora temos uma documentação muito mais extensa sobre o gerenciamento da memória do seu aplicativo, que abrange grande parte do material aqui e está mais atualizado com o estado do Android.
A primeira coisa é provavelmente ler a última parte deste artigo, que discute como a memória é gerenciada no Android:
Alterações na API de serviço iniciadas no Android 2.0
Agora
ActivityManager.getMemoryInfo()
é a nossa API de nível mais alto para analisar o uso geral da memória. Isso está presente principalmente para ajudar um aplicativo a avaliar o quão perto o sistema está de não ter mais memória para processos em segundo plano, necessitando, assim, começar a eliminar processos necessários, como serviços. Para aplicativos Java puros, isso deve ser de pouca utilidade, pois o limite de heap Java existe em parte para evitar que um aplicativo consiga forçar o sistema até esse ponto.No nível inferior, você pode usar a API Debug para obter informações brutas no nível do kernel sobre o uso da memória: android.os.Debug.MemoryInfo
Observe que, começando com 2.0, também há uma API,
ActivityManager.getProcessMemoryInfo
para obter essas informações sobre outro processo: ActivityManager.getProcessMemoryInfo (int [])Isso retorna uma estrutura MemoryInfo de baixo nível com todos esses dados:
Mas, como o que é a diferença entre
Pss
,PrivateDirty
eSharedDirty
... bem, agora a diversão começa.Muita memória no Android (e sistemas Linux em geral) é realmente compartilhada entre vários processos. Portanto, quanta memória um processo usa não é realmente clara. Adicione ainda mais a paginação em disco (sem falar na troca que não usamos no Android) e fica ainda menos claro.
Portanto, se você pegar toda a RAM física realmente mapeada para cada processo e adicionar todos os processos, provavelmente terminará com um número muito maior que a RAM total real.
O
Pss
número é uma métrica que o kernel calcula que leva em consideração o compartilhamento de memória - basicamente cada página de RAM em um processo é dimensionada por uma proporção do número de outros processos que também usam essa página. Dessa forma, você pode (em teoria) adicionar os pss em todos os processos para ver a RAM total que eles estão usando e comparar pss entre processos para obter uma idéia aproximada de seu peso relativo.A outra métrica interessante aqui é
PrivateDirty
, que é basicamente a quantidade de RAM dentro do processo que não pode ser paginada em disco (não é suportada pelos mesmos dados em disco) e não é compartilhada com outros processos. Outra maneira de olhar para isso é a RAM que ficará disponível para o sistema quando esse processo for encerrado (e provavelmente submergiu rapidamente em caches e outros usos).Essas são as APIs do SDK para isso. No entanto, há mais que você pode fazer como desenvolvedor com seu dispositivo.
Usando
adb
, há muitas informações que você pode obter sobre o uso de memória de um sistema em execução. Um comando comum é o comandoadb shell dumpsys meminfo
que fornecerá várias informações sobre o uso da memória de cada processo Java, contendo as informações acima e várias outras coisas. Você também pode usar o nome ou o pid de um único processo para ver, por exemplo,adb shell dumpsys meminfo system
me dê o processo do sistema:A seção superior é a principal, onde
size
é o tamanho total no espaço de endereço de um heap específico,allocated
é o kb de alocações reais que o heap pensa que possui,free
é o kb restante livre do heap para alocações adicionaispss
epriv dirty
são os mesmos conforme discutido anteriormente, específico para páginas associadas a cada um dos montes.Se você só quer olhar para o uso de memória em todos os processos, você pode usar o comando
adb shell procrank
. A saída disso no mesmo sistema é semelhante a:Aqui, as colunas
Vss
eRss
são basicamente ruídos (esses são o espaço de endereço direto e o uso de RAM de um processo, onde se você adicionar o uso de RAM nos processos, obtém um número ridiculamente grande).Pss
é como vimos antes, eUss
éPriv Dirty
.É interessante notar aqui:
Pss
eUss
são um pouco (ou mais que um pouco) diferentes do que vimosmeminfo
. Por que é que? Bem, procrank usa um mecanismo de kernel diferente para coletar seus dados do quememinfo
faz, e eles fornecem resultados ligeiramente diferentes. Por que é que? Honestamente, eu não tenho idéia. Eu acredito queprocrank
pode ser o mais preciso ... mas, na verdade, isso deixa o ponto: "pegue qualquer informação de memória obtida com um grão de sal; geralmente um grão muito grande".Finalmente, há o comando
adb shell cat /proc/meminfo
que fornece um resumo do uso geral de memória do sistema. Há muitos dados aqui, apenas os primeiros números que vale a pena discutir (e os demais são entendidos por poucas pessoas, e minhas perguntas sobre essas poucas pessoas sobre eles geralmente resultam em explicações conflitantes):MemTotal
é a quantidade total de memória disponível para o kernel e o espaço do usuário (geralmente menor que a RAM física real do dispositivo, pois parte dessa RAM é necessária para o rádio, os buffers de DMA, etc.).MemFree
é a quantidade de RAM que não está sendo usada. O número que você vê aqui é muito alto; normalmente em um sistema Android, isso teria apenas alguns MB, já que tentamos usar a memória disponível para manter os processos em execuçãoCached
é a RAM que está sendo usada para caches do sistema de arquivos e outras coisas. Os sistemas típicos precisarão ter aproximadamente 20 MB para evitar problemas de paginação; o assassino de falta de memória do Android é ajustado para um sistema específico para garantir que os processos em segundo plano sejam eliminados antes que a RAM em cache seja consumida demais por eles para resultar em tal paginação.fonte
Sim, você pode obter informações de memória programaticamente e decidir se deve fazer um trabalho intensivo de memória.
Obtenha o tamanho de heap da VM ligando para:
Obtenha memória VM alocada chamando:
Obtenha o Limite de tamanho de heap da VM chamando:
Obter memória alocada nativa chamando:
Eu criei um aplicativo para descobrir o comportamento do OutOfMemoryError e monitorar o uso da memória.
https://play.google.com/store/apps/details?id=net.coocood.oomresearch
Você pode obter o código fonte em https://github.com/coocood/oom-research
fonte
Este é um trabalho em andamento, mas é isso que eu não entendo:
Por que o PID não é mapeado para o resultado em activityManager.getProcessMemoryInfo ()? Claramente, você deseja tornar os dados resultantes significativos. Por que o Google tornou tão difícil correlacionar os resultados? O sistema atual nem funciona bem se eu quiser processar todo o uso da memória, pois o resultado retornado é uma matriz de objetos android.os.Debug.MemoryInfo, mas nenhum desses objetos realmente diz a que pids eles estão associados. Se você simplesmente passar uma série de todos os pids, não terá como entender os resultados. Pelo que entendi, é inútil passar mais de um pid de cada vez e, se for esse o caso, por que fazê-lo para que activityManager.getProcessMemoryInfo () use apenas uma matriz int?
fonte
O Hackbod's é uma das melhores respostas no Stack Overflow. Lança luz sobre um assunto muito obscuro. Isto me ajudou bastante.
Outro recurso realmente útil é este vídeo imperdível: Google I / O 2011: Gerenciamento de memória para aplicativos Android
ATUALIZAR:
Process Stats, um serviço para descobrir como o aplicativo gerencia a memória explicada na postagem do blog Stats do Processo: Entendendo como o aplicativo usa a RAM de Dianne Hackborn:
fonte
O Android Studio 0.8.10+ introduziu uma ferramenta incrivelmente útil chamada Monitor de Memória .
Para que serve:
Figura 1. Forçando um evento de GC (Garbage Collection) no Android Memory Monitor
Você pode obter muitas informações boas sobre o consumo de RAM em tempo real do seu aplicativo usando-o.
fonte
1) Acho que não, pelo menos não do Java.
2)
fonte
Descobrimos que todas as formas padrão de obter a memória total do processo atual têm alguns problemas.
Runtime.getRuntime().totalMemory()
: retorna apenas memória JVMActivityManager.getMemoryInfo()
,Process.getFreeMemory()
E qualquer outra coisa com base em/proc/meminfo
- retorna informação de memória sobre todos os processos combinados (por exemplo android_util_Process.cpp )Debug.getNativeHeapAllocatedSize()
- usosmallinfo()
que retornam informações sobre alocações de memória executadas apenas pormalloc()
e funções relacionadas (consulte android_os_Debug.cpp )Debug.getMemoryInfo()
- faz o trabalho, mas é muito lento. Demora cerca de 200 ms no Nexus 6 para uma única chamada. A sobrecarga de desempenho torna essa função inútil para nós, como a chamamos regularmente e todas as chamadas são bastante visíveis (consulte android_os_Debug.cpp )ActivityManager.getProcessMemoryInfo(int[])
- chamaDebug.getMemoryInfo()
internamente (consulte ActivityManagerService.java )Por fim, acabamos usando o seguinte código:
Retorna a métrica VmRSS . Você pode encontrar mais detalhes sobre isso aqui: um , dois e três .
PS : Observei que o tema ainda não possui um trecho de código real e simples de como estimar o uso de memória privada do processo, se o desempenho não for um requisito crítico:
fonte
No android studio 3.0, eles introduziram o android-profiler para ajudar você a entender como o aplicativo usa os recursos de CPU, memória, rede e bateria.
https://developer.android.com/studio/profile/android-profiler
fonte
Há muitas respostas acima que definitivamente o ajudarão, mas (após 2 dias de recursos e pesquisas em ferramentas de memória adb) , acho que também posso ajudar com minha opinião .
Como Hackbod diz: Portanto, se você pegasse toda a RAM física realmente mapeada para cada processo e adicione todos os processos, provavelmente terminaria com um número muito maior que a RAM total real. portanto, não há como obter quantidade exata de memória por processo.
Mas você pode se aproximar disso por alguma lógica .. e eu direi como ..
Então, primeiro você precisa ser um usuário root para fazer funcionar. Entre no console com privilégio root executando
su
no processo e obtenha seuoutput and input stream
. Em seguida, passeid\n
(enter) no fluxo de saída e escreva-o para processar a saída. Se obter um fluxo de entrada contendouid=0
, você é usuário root.Agora, aqui está a lógica que você usará no processo acima
Quando você obtém ouputstream do processo, você comando (procrank, dumpsys meminfo etc ...) com
\n
vez de id e obtenhainputstream
e leia, armazene o fluxo em bytes [], char [] etc. use dados brutos .. e você está feito !!!!!permissão:
Verifique se você é usuário root:
Execute seu comando com
su
logcat:
Esta é apenas uma tentativa, por favor, sugira-me se eu perdi alguma coisa
fonte