Otimização de desempenho do Android - resumo da análise de otimização de memória

1. Conceito de otimização de memória

1.1 Por que precisamos otimizar a memória?

A otimização da memória sempre foi um ponto muito importante, mas carece de atenção. Como um dos recursos mais importantes para a execução do programa, a memória precisa ser razoavelmente alocada e reciclada durante a operação. O uso irracional da memória pode até fazer com que o aplicativo do usuário seja executado. Gagueira, ANR , e a tela preta pode até causar falhas de OOM (falta de memória) nos aplicativos do usuário. Se você seguir com atenção, poderá descobrir que o local onde ocorre o problema de memória é apenas uma manifestação, não a causa profunda, porque o problema de memória é relativamente complexo. É um processo de compressão gradual e acontece em o código onde você tem o problema. Explodiu, então os desenvolvedores devem prestar mais atenção aos problemas de memória do aplicativo.

1.2 Manifestações de problemas de memória

  • Tremulação de memória: GC irregular e frequente causando atrasos

  • Vazamento de memória: a memória disponível diminui gradualmente, GC frequente

  • Estouro de memória: OOM, exceção de programa

2. Ferramentas de análise de memória comumente usadas

Para resolver problemas de memória, devemos ter ferramentas poderosas de análise de memória que nos permitam localizar problemas de memória de forma mais rápida e conveniente. As principais ferramentas atuais de análise de memória incluem principalmente LeakCanary, Memory Profiler e MAT.

2.1 VazamentoCanário

LeakCanary é uma estrutura de monitoramento de vazamento de memória de código aberto da Square. Os vazamentos de memória que ocorrem enquanto o aplicativo está em execução serão monitorados e registrados pelo LeakCanary.

 Análise de rastreamento de vazamento de memória LeakCanary, observando principalmente o rastreamento de Vazamento: NÃO para Vazamento: SIM, você pode descobrir que TextView tem um vazamento de memória porque contém o contexto da atividade destruída.

Para uma análise de rastreamento mais específica, você pode visualizar o documento oficial Corrigindo um vazamento de memória.

Embora usar o LeakCanary seja muito conveniente, ele também tem algumas desvantagens:

  • A referência direta ao LeakCanary usado pelas dependências geralmente é usada para depuração offline e precisa ser fechada quando o aplicativo é lançado online.

  • A depuração de aplicativos às vezes causa atrasos

Portanto, geralmente o uso do LeakCanary é apenas uma maneira simples de localizar vazamentos de memória. No entanto, se você precisar de uma melhor otimização de memória, como localização de jitter de memória, otimização de bitmap, etc., ainda precisará de outras ferramentas de análise. As principais comumente usadas são Memória Perfilador e MAT.

2.2 NativeSize、Tamanho Raso、Tamanho Retido、Profundidade

Ao descrever o Memory Profiler e o MAT posteriormente, vários indicadores mais importantes aparecerão com frequência: Tamanho Raso e Tamanho Retido. Tamanho e profundidade nativos também são fornecidos no Memory Profiler.

Depois de obter um Heap Dump, o Memory Profiler exibirá uma lista de classes. Para cada classe, a coluna Alocações mostra o número de instâncias. À direita estão Tamanho Nativo, Tamanho Raso e Tamanho Retido:

Usamos a figura abaixo para representar o status da memória do aplicativo registrado por uma determinada seção do Heap Dump. Preste atenção ao nó vermelho. Neste exemplo, o objeto representado por este nó refere-se ao objeto Native do nosso projeto; esta situação é menos comum, mas após o Android 8.0, tal situação pode ocorrer ao usar Bitmap, porque Bitmap irá armazenar informações de pixel na memória nativa para reduzir a pressão de memória na JVM.

Vamos começar com Shallow Size. Esta coluna de dados é na verdade muito simples. É o tamanho da memória consumida pelo próprio objeto.

Profundidade é o caminho mais curto da raiz do GC até esta instância. Os números na figura são a profundidade (Profundidade) de cada objeto.

Quanto mais próximo um objeto estiver da raiz do GC, maior será a probabilidade de ele estar conectado à raiz do GC por meio de vários caminhos e maior será a probabilidade de ser salvo durante a coleta de lixo.

Tomando o nó vermelho como exemplo, se qualquer referência do lado esquerdo dele for destruída, o nó vermelho ficará inacessível e será coletado como lixo. Para o nó azul à direita, se quiser que ele seja coletado como lixo, você precisa destruir os caminhos à esquerda e à direita.

É importante notar que se você vir uma instância com Profundidade 1, significa que ela é referenciada diretamente pelo GC Root, o que também significa que ela nunca será reciclada automaticamente.

Abaixo está um exemplo de Activity que implementa a interface LocationListener. A parte destacada do código, requestLocationUpdates(), usará a instância atual da Activity para registrar o locationManager. Se você esquecer de sair, esta atividade irá vazar. Ele ficará na memória para sempre, pois o gerenciador de localização é um GC Root e sempre existirá:

Você pode ver isso no Memory Profiler. Clique em uma instância e o Memory Profiler abrirá um painel mostrando quem está fazendo referência à instância:

Podemos ver que o mListener no gerenciador de localização está fazendo referência a esta atividade. Você pode dar um passo adiante e navegar até a visualização de referência do heap por meio do painel Referências, que permitirá verificar se a cadeia de referência é o que você espera e também ajudará a entender se e onde há vazamentos em seu código.

2.3 Perfilador de memória

Memory Profiler é uma ferramenta de análise de memória integrada ao Android Studio adequada para visualizar condições de memória em tempo real.

2.3.1 Descrição da interface do Memory Profiler

Documentação oficial: Use o Memory Profiler para visualizar o heap Java e a alocação de memória

2.3.2 Memory Profiler para encontrar jitter de memória

Encontrar o jitter da memória é relativamente simples. O programa em execução aparecerá no Memory Profiler conforme a memória flutua para cima e para baixo em um curto período de tempo, acionando a reciclagem do GC com frequência.

Locais comuns onde ocorre instabilidade de memória:

  • Personalize onMeasure(), onLayout(), onDraw() do View para criar objetos diretamente com novos

  • Listas como onBindViewHolder() do RecyclerView criam diretamente objetos com novos

  • Criando objetos em código com loops

Use um caso simples para simular a destruição da memória:

publicclassMainActivityextendsAppCompatActivity {
​@SuppressWarnings("HandlerLeak")privateHandler mHandler = newHandler() {@OverridepublicvoidhandleMessage(Message msg) {// 模拟内存抖动for (int i = 0; i < 100; i++) {String[] args = newString[100000];}
​mHandler.sendEmptyMessageDelayed(0, 30);}};
​@OverrideprotectedvoidonCreate(@Nullable Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);
​findViewById(R.id.button).setOnClickListener(newView.OnClickListener() {@OverridepublicvoidonClick(View v) {mHandler.sendEmptyMessage(0);}});}
}
复制代码

O caso é muito simples, ou seja, objetos são criados frequentemente quando o botão é clicado. A execução do programa acima em uma máquina real pode não causar flutuações irregulares de memória, mas haverá reciclagem de GC muito frequente, conforme mostrado na figura abaixo:

Então, como devemos localizar especificamente onde ocorre o tremor de memória?

Siga as etapas acima:

  • Posição ①: Quando o programa estiver em execução, clique no botão Gravar para registrar o status da memória e, em seguida, clique em Parar para interromper a gravação. A imagem acima será exibida.

  • Posição ②: Podemos clicar em Alocações para visualizar o número de objetos alocados em ordem decrescente de grande para pequeno ou em ordem crescente de pequeno para grande. Geralmente, optaremos por visualizar o maior número de objetos em ordem decrescente de grande para pequeno. O objeto com o maior número de objetos na figura acima é o objeto String

  • Posição ③: Selecione um objeto String na Visualização de Instância e a Pilha de Chamadas de Alocação abaixo será exibida. Ele exibirá a localização da pilha de chamadas deste objeto.

  • Posição ④: Na Pilha de Chamadas de Alocação, podemos ver que o objeto String é criado em handleMessage() na linha 18 de MainActivity, localizando assim a localização do jitter de memória.

Existem algumas dicas para a operação acima:

  • Antes de operar na posição ①, para eliminar interferências, a memória alterada geralmente será GCed manualmente antes da gravação; em dispositivos acima do Android 8.0, você pode arrastar o Memory Profiler em tempo real para selecionar a faixa de flutuação da memória a ser visualizada.

  • Posição ② O exemplo acima é para visualizar diretamente a organização por classe, mas em projetos reais, é mais provável escolher Organizar por pacote para visualizar as classes sob o nome do pacote do seu projeto

2.3.3 Memory Profiler para encontrar vazamentos de memória

Como mencionado acima, a manifestação de vazamento de memória é que ocorrerá jitter de memória, porque quando ocorre um vazamento de memória, a memória disponível continua a diminuir.Quando o sistema precisa de memória, o GC ocorrerá quando a memória for insuficiente, então ocorre jitter de memória.

Quando ocorre um vazamento de memória, o Memory Profiler mostrará uma tendência ascendente semelhante de memória escalonada e a memória não cairá:

O vazamento de memória na imagem acima é bastante óbvio. Quando ocorre um vazamento de memória no desenvolvimento real do projeto, pode não ser particularmente óbvio. Levará muito tempo para executar e descobrir que a memória está aumentando lentamente. Neste momento, o dump heap é necessário para ajudar na localização.

A seguir, explicaremos brevemente como usar o Memory Profiler para analisar vazamentos de memória usando o caso de vazamentos de memória do Handler.

public classHandlerLeakActivityextendsAppCompatActivity{private static finalStringTAG = HandlerLeakActivity.class.getSimpleName();
​privateHandler handler = newHandler() {@Overridepublic void handleMessage(Message msg) {if (msg.what == 0) {Log.i(TAG, "handler receive msg");}}};
​@Overrideprotected void onCreate(@NullableBundle savedInstanceState) {super.onCreate(savedInstanceState);handler.sendEmptyMessageDelayed(0, 10 * 1000);}
}
复制代码

O código acima é muito simples: após iniciar o aplicativo, toda vez que você entrar em HandlerLeakActivity, use o Handler para atrasar o envio de mensagens por 10 segundos, saia da interface em 10 segundos e repita a operação.

1. Repita a operação que pode causar vazamentos de memória várias vezes e o heap do Memory Profiler despeja o arquivo hprof (recomenda-se eliminar a interferência do GC antes da operação)

2. Visualize o arquivo de despejo de heap hprof no Memory Profiler:

Pode-se descobrir que após o GC manual, Allocations mostra 5 HandlerLeakActivities, e várias instâncias de Activity ainda são exibidas no heap dump Instance View, indicando que ocorreram vazamentos de memória. O local específico do vazamento de memória pode ser clicado no objeto de classe de instância vazado em Visualização de Instância. Visualização, a Referência abaixo da Visualização de Instância exibirá a cadeia de referência específica.

Na nova versão do Memory Profiler, a caixa de seleção Vazamentos de atividade/fragmento é fornecida. Selecioná-la pode encontrar diretamente a localização de possíveis vazamentos de memória:

2.4 TAPETE

2.4.1 Introdução ao MAT

  • Poderosa ferramenta de análise Java Heap para encontrar vazamentos e uso de memória

  • Gere relatórios gerais, analise problemas e muito mais

  • Uso offline aprofundado

Endereço oficial de download do site: www.eclipse.org/mat/downloa... , este endereço contém palavras com as quais você está familiarizado? Bem, isso mesmo, MAT é um plug-in no Eclipse, porque muitas pessoas agora usam IDEA no processo de desenvolvimento Ou Android Studio, então se você não quiser baixar o Eclipse, você pode baixar a versão independente do MAT. Após a descompactação, há um arquivo executável do MemoryAnalyzer.exe nele. Você pode usá-lo clicando nele.

Muitas vezes precisamos usar essa ferramenta em conjunto com o recurso de heap dump do Android Studio. No entanto, deve-se observar que o arquivo hprof gerado após AS3.0 não é um arquivo hprof padrão. Você precisa usar o comando para convertê-lo : hprof-conv Depois de converter o caminho do arquivo original caminho do arquivo

2.4.2 Introdução ao uso do MAT

①. Visão geral: informações gerais

Principais consumidores

  • Objetos que ocupam mais memória são exibidos em gráficos. Esta coluna é mais útil para reduzir o uso de memória.

  • Maiores Objetos: informações relativamente detalhadas

Suspeitos de vazamento

  • Verifique rapidamente pontos suspeitos de vazamento de memória

②, Histograma: Histograma

  • Nome da classe: pesquise especificamente por uma determinada classe

  • Objetos: quantas instâncias de uma classe específica existem

  • Shallow Heap: quanta memória uma única instância ocupa?

  • Heap retido: quanta memória esses objetos ocupam no total nesta cadeia de referência?

Agrupar por pacote: exibe objetos de classe na forma de nomes de pacotes

Listar objetos

  • com referências de saída: Quais classes são referenciadas por si só?

  • com referências recebidas: quais classes são referenciadas por

③、dominator_tree

  • Árvore de dominação para cada objeto

  • porcentagem: porcentagem de todos os objetos

Clique com o botão direito no item e ele também terá objetos List. Qual a diferença entre ele e o Histograma? As principais diferenças são os dois pontos a seguir:

  • Histograma: análise de perspectiva baseada em classe

  • dominator_tree: análise de perspectiva baseada em exemplo

④. OQL: Linguagem de consulta de objetos, semelhante à recuperação de conteúdo de um banco de dados

⑤, thread_overview: Exibição detalhada de informações do thread, você pode ver quantos threads existem atualmente na memória

3. Solução prática de jitter de memória

3.1 Introdução ao jitter de memória

  • Definição: alocação e reciclagem freqüentes de memória levam à instabilidade da memória

  • Desempenho: GC frequente, curva de memória irregular

  • Perigos: Causando atraso e, em casos graves, OOM.

3.2 Jitter de memória causa OOM

  • A criação frequente de objetos leva à memória insuficiente e à fragmentação (descontinuidade)

  • Fatias de memória descontínuas não podem ser alocadas, resultando em OOM

3.3 Análise prática

Nesta parte, simularei um jitter de memória, analisarei a situação da memória por meio do Profiler e localizarei o código específico de jitter de memória.

Primeiro, vamos criar um arquivo de layout Activity_memory.xml, que contém um botão para acionar a parte do código que simula o jitter de memória:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:orientation="vertical" android:layout_width="match_parent"android:layout_height="match_parent"><Buttonandroid:id="@+id/btn_memory"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="模拟内存抖动"/>
</LinearLayout>
复制代码

Em seguida, defina uma página MemoryShakeActivity, carregue o layout agora mesmo e defina um Handler na página. Quando o botão para simular agitação de memória é clicado, executamos regularmente o código para simular agitação em handleMessage. Todo o código é fácil de entender. kind :

/*** 说明:模拟内存抖动页面*/publicclassMemoryShakeActivityextendsAppCompatActivityimplementsView.OnClickListener {@SuppressLint("HandlerLeak")privatestaticHandler mHandler = newHandler(){@OverridepublicvoidhandleMessage(@NonNull Message msg) {super.handleMessage(msg);//模拟内存抖动的场景,每隔10毫秒执行一次,循环执行100次,每次通过new分配大内存for (int i=0;i<100;i++){String[] obj = newString[100000];}mHandler.sendEmptyMessageDelayed(0,10);}};@OverrideprotectedvoidonCreate(@Nullable Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_memory);findViewById(R.id.btn_memory).setOnClickListener(this);}@OverridepublicvoidonClick(View view) {if (view.getId() == R.id.btn_memory){mHandler.sendEmptyMessage(0);}}@OverrideprotectedvoidonDestroy() {super.onDestroy();mHandler.removeCallbacksAndMessages(null);}
}
复制代码

Aí corri e tirei duas screenshots para todo mundo ver, a primeira é antes da execução do código que simula o jitter e a segunda é depois da execução:

A partir das duas imagens acima, você pode ver claramente que a primeira imagem de memória é relativamente estável, e a segunda imagem de memória tem uma aparência irregular e ocorre GC repentino e frequente. Você vê muitas pequenas latas de lixo abaixo? Neste momento, você pode fazer um julgamento preliminar de que deveria ser O fenômeno do jitter de memória aparece, porque está mais de acordo com suas características, então arraste uma certa distância no painel e ele nos mostrará a alocação de memória durante este período:

Primeiro clique duas vezes em Alocações e, em seguida, organize esta coluna na ordem do maior para o menor, e então você descobrirá que existem muitos arrays de String e também ocupa o maior tamanho de memória (marquei os pontos dignos de atenção com retângulos), devemos bloquear esse alvo neste momento. Por que existem tantos arrays do tipo String? Provavelmente há um problema aqui. Em seguida, solucione o que está causando esse problema. É muito simples clicar na linha String[] e clicar em qualquer linha no painel Instance View à direita. As informações da pilha correspondente aparecerão no painel Allocation Call Stack abaixo. O específico informações também estão listadas acima. Para qual linha de qual classe, clique com o botão direito do mouse em jupm para a fonte para pular para o local do código-fonte especificado. Dessa forma, podemos encontrar o local onde ocorre o jitter de memória e, em seguida, podemos analisar o código e faça as modificações correspondentes.

Resumo do processo:

  1. Solução de problemas preliminar usando Memory Profiler;

  1. Use Memory Profiler ou CPU Profiler para solucionar problemas de código

Habilidades de solução de jitter de memória: encontre loops ou locais que são chamados com frequência

4. Resolução real de vazamento de memória

4.1 Introdução aos vazamentos de memória

Definição: não há mais objetos úteis na memória

Desempenho: tremulação de memória, memória disponível diminui gradualmente

Perigos: Memória insuficiente, GC frequente, OOM

4.2 Análise Real do Combate

Aqui ainda usamos código para simular verdadeiramente um cenário de vazamento de memória. Para programas APP em geral, o maior problema geralmente é o Bitmap, porque consome mais memória e será mais óbvio usá-lo para simular. Bem, primeiro vamos dar uma olhada no arquivo de layout Activity_memoryleak.xml, que contém um controle ImageView:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><ImageViewandroid:id="@+id/iv_memoryleak"android:layout_width="50dp"android:layout_height="50dp" />
</LinearLayout>
复制代码

Em seguida, definimos uma interface Callback que simula o processamento de determinados serviços e uma classe Manager que gerencia uniformemente essas interfaces de callback:

//模拟回调处理某些业务场景publicinterfaceCallBack {voiddpOperate();
}//统一管理CallbackpublicclassCallBackManager {publicstatic ArrayList<CallBack> sCallBacks = new ArrayList<>();publicstaticvoidaddCallBack(CallBack callBack) {sCallBacks.add(callBack);}publicstaticvoidremoveCallBack(CallBack callBack) {sCallBacks.remove(callBack);}
}
复制代码

Em seguida, defina o Bitmap em nossa página simulada de vazamento de memória e configure a escuta de retorno de chamada:

/*** 说明:模拟内存泄露页面*/
public classMemoryLeakActivityextendsAppCompatActivityimplementsCallBack{@Overrideprotected void onCreate(@NullableBundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_memoryleak);ImageView imageView = findViewById(R.id.iv_memoryleak);Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.big_bg);imageView.setImageBitmap(bitmap);CallBackManager.addCallBack(this);}@Overridepublic void dpOperate() {}
}
复制代码

OK, nosso código foi escrito. Agora vamos executá-lo e, em seguida, abrir e fechar esta página várias vezes consecutivas para ver se esse código causará um vazamento de memória.

Esta é uma imagem de memória que capturei com o Profiler. Você pode ver que toda a memória apresenta uma pequena instabilidade em alguns lugares depois que troquei de página repetidamente. No entanto, a memória geral aumenta em forma de escada e a memória disponível diminui gradualmente. Basicamente pode-se concluir que há um vazamento de memória nesta interface. Embora a ferramenta Profiler possa inicialmente nos ajudar a determinar que ocorreu um vazamento de memória, ela não pode determinar onde ocorreu o vazamento de memória. Isso significa que ainda não sabemos onde modificar o código, então precisamos usar a poderosa ferramenta Java Heap neste momento., Venha e convide MAT para jogar.

Primeiro, você precisa clicar no botão Dump Java Heap no Profiler, usar a função heap dump para convertê-lo em um arquivo e, em seguida, clicar no botão Salvar para salvar o arquivo em um diretório local. Por exemplo, eu o salvo como o arquivo memoryleak.hprof na unidade H e, em seguida, use hprof O comando -conv converte-o em um arquivo hprof padrão. O nome convertido aqui é: memoryleak_transed.hprof, conforme mostrado abaixo:

Em seguida, abra a ferramenta MAT e importe o arquivo convertido recém-gerado:

Clique no Histograma para visualizar todos os objetos sobreviventes na memória, e então podemos inserir o conteúdo no Nome da Classe para procurar o objeto que queremos encontrar:

Então você pode ver as informações específicas do objeto, bem como o número e o tamanho da memória ocupada. Descobri que na verdade existem 6 objetos MemoryLeakActivity na memória:

Em seguida, clique com o botão direito em Listar objetos ----> com referências recebidas para encontrar todas as referências fortes que levam a ele:

Em seguida, clique com o botão direito em Path To GC Roots----->com todas as referências, conte todas as referências e calcule o caminho entre este objeto e o GCRoot:

Olhando os resultados, finalmente chegamos a sCallBacks, e há um pequeno círculo no canto inferior esquerdo dele. Este é o local que realmente estamos procurando, o que significa que MemoryLeakActivity é referenciado pelo objeto sCallBacks da classe CallBackManager:

Com base nos resultados encontrados acima, vá até o código para encontrar sCallBacks do CallBackManager para ver o que exatamente está acontecendo aqui.

publicstaticArrayList<CallBack> sCallBacks = new ArrayList<>();
复制代码

MemoryLeakActivity é referenciado pela variável estática sCallBacks. Como o ciclo de vida da variável modificada pela palavra-chave estática é tão longo quanto todo o ciclo de vida do App, quando a página MemoryLeakActivity for fechada, devemos liberar o relacionamento de referência da variável. , caso contrário, haverá o problema de vazamento de memória acima. Então resolver esse problema também é muito simples, adicione as seguintes linhas de código:

@OverrideprotectedvoidonDestroy() {super.onDestroy();CallBackManager.removeCallBack(this);
}
复制代码

Resumo do processo:

  1. Use o Memory Profiler para observação inicial (a memória disponível diminui gradualmente);

  1. Combinado com confirmação de código através do Memory Analyzer

5. Solução de monitoramento de memória online

O maior problema de memória online são os vazamentos de memória. O tremor e o estouro de memória geralmente estão relacionados à incapacidade de liberar memória causada por vazamentos de memória. Se os vazamentos de memória puderem ser resolvidos, os problemas de memória online serão bastante reduzidos. O monitoramento de memória online é bastante difícil porque não podemos usar essas ferramentas offline para descobrir e analisar problemas intuitivamente.

5.1 Esquema Convencional

①. Definir despejo de cena on-line

Por exemplo, se seu aplicativo ocupou uma porcentagem maior da memória máxima disponível de um único aplicativo, como 80%, passe: Debug.dumpHprofData(); esta linha de código pode converter as informações de memória atuais em um arquivo local.

Todo o processo é o seguinte: Mais de 80% da memória -> Memory Dump -> Retornar o arquivo (observe que o arquivo pode ser grande, mantenha-o no estado wifi e devolva-o) -> Análise manual do MAT

Resumir:

  • O arquivo de despejo é muito grande, o que está positivamente relacionado ao número de objetos e pode ser cortado

  • Alta taxa de falha de upload e análise difícil

②. Use o LeakCanary on-line

  • LeakCanary traz online

  • Ponto duvidoso de vazamento padrão

  • Descubra retornos de chamada vazados

Resumir:

  • Não é adequado para todas as situações. As dúvidas devem ser pré-definidas, o que limita a abrangência.

  • A análise é demorada e propensa a OOM (na prática, verifica-se que o processo de análise do LeakCanary é lento e é muito provável que ocorra OOM durante o processo de análise)

5.2 Personalização do LeakCanary

  • Pontos de suspeita predefinidos —— "Encontrar pontos de suspeita automaticamente (suspeite de quem tem uma grande pegada de memória, a probabilidade de problemas com objetos de grande memória é maior)

  • Análise lenta de links vazados (analisar cada objeto do objeto predefinido) -> Analisar objetos com grande tamanho de retenção (reduzir sua carga de trabalho de análise e aumentar a velocidade de análise)

  • Analisar OOM (mapear todos os arquivos gerados pela pilha de memória para a memória, o que ocupa mais memória) -> Corte de objetos, nem todos carregados na memória

5.3 Solução completa para monitoramento online

  • Memória em espera, memória do módulo principal, taxa OOM

  • Tempos de GC do módulo geral e principal e tempo de GC

  • Análise aprimorada de vazamento de memória automatizada LeakCanary

6. Habilidades de otimização de memória

Direção geral de otimização:

  • vazamento de memória

  • destruição de memória

  • Mapa de bits

Detalhes de otimização:

  • Atributo LargeHeap (embora seja um pouco desonesto, ainda deve ser aplicado ao sistema)

  • onTrimMemory, onLowMemory (o retorno de chamada com pouca memória fornecido pelo sistema pode lidar com alguma lógica de acordo com diferentes níveis de retorno de chamada)

  • Use coleções otimizadas: SparseArray

  • Use SharedPreference com cuidado (carregamento único na memória)

  • Use bibliotecas externas com cuidado (tente escolher bibliotecas externas que tenham sido verificadas em larga escala)

  • A arquitetura de negócios é razoavelmente projetada (os dados carregados são o que você pode usar, nenhuma memória é desperdiçada carregando dados inúteis)

 

Acho que você gosta

Origin blog.csdn.net/qq_25462179/article/details/132737973
Recomendado
Clasificación