Pergunta

Eu tenho um problema de vazamento de memória no meu aplicativo Flex, e a versão curta da minha pergunta é: existe alguma maneira (no Acitonscript 3) para encontrar todas as referências ao vivo a um determinado objeto?

O que eu tenho é uma série de visualizações com modelos de apresentação por trás de cada um deles (usando o SWIZ). As visões de interesse são filhos de um tabnavigator; portanto, quando eu fecho a guia, a visualização é removida do palco. Quando a visualização é removida do palco, o Swiz define a referência do modelo na vista para NULL, como deveria. Eu também removi () () da vista.

No entanto, ao perfilar o aplicativo, quando eu faço isso e executar um GC, nem a visualização nem o modelo de apresentação são libertados (embora ambos defina suas referências entre si como nulos). Um objeto de modelo usado pela visualização (não é um apresentador, no entanto) é libertado, por isso não está completamente quebrado.

Acabei de começar a perfilar hoje (acreditando firmemente em não otimizar muito cedo), então imagino que haja algum tipo de referência flutuando em algum lugar, mas não consigo ver onde e o que seria super útil seria a capacidade de depurar depurar e veja uma lista de objetos que referenciam o objeto de destino. Isso é possível e, se não nativamente, existe uma maneira leve de codificar isso em futuros aplicativos para fins de depuração?

Felicidades.

Foi útil?

Solução

Supondo que você esteja usando o Flex Builder, você pode experimentar o Profiler. Na minha experiência, não é tão bom para o desempenho do perfil, mas foi de grande ajuda para encontrar vazamentos de memória.

Não é a ferramenta mais intuitiva e leva um tempo para se acostumar (quero dizer, a ponto de realmente se tornar útil). Mas, na minha opinião, investir algum tempo para pelo menos aprender o básico compensa. Há uma enorme diferença entre ver quanta memória o jogador está usando globalmente (o que o System.Totalmemory oferece, um indicador muito difícil, impreciso e muitas vezes enganoso) e, na verdade, rastrear quantas instâncias de cada objeto foram criadas, quantos ainda são vivo e onde eles foram alocados (para que você possa encontrar o vazamento potencial no código e realmente consertá -lo em vez de confiar na magia negra).

Não conheço nenhum bom tutorial para o FB Profiler, mas talvez isso ajude a começar.

Primeiro, lance o Profiler. Desmarque o perfil de desempenho e verifique todo o resto (ative o perfil da memória, assista dados de memória ao vivo e gerar rastreadores de pilha de alocação de objetos).

Quando o Profiler iniciar, você verá estatísticas sobre os objetos do aplicativo, agrupados por classe. Neste ponto, você pode querer ajustar os filtros. Você verá muitos dados e é muito fácil ficar sobrecarregado. Por enquanto, ignore tudo o que é nativo e flexível, se possível, e concentre -se em algum objeto que você acha que deve ser coletado.

Os números mais importantes são "instâncias cumulativas" e "instâncias". O primeiro é o número total de instâncias criadas até agora; O segundo, o número dos referidos casos que ainda estão vivos. Portanto, um bom ponto de partida é levar seu aplicativo ao estado em que a visão suspeita de que os vazamentos são criados. Você deve ver 1 para "instâncias cumulativas" e "instâncias".

Agora, faça o que for necessário para chegar ao ponto em que essa visualização deve ser limpa (navegue para outra parte do aplicativo, etc.) e execute um GC (há um botão para isso na interface do usuário do Profiler). Um ponto crucial é que você estará verificando o comportamento do aplicativo em relação às suas expectativas -se fizer sentido. Encontrar vazamentos automaticamente em um ambiente coletado de Garbarge é quase impossível por definição; Caso contrário, não haveria vazamentos. Então, lembre -se disso: você testa suas expectativas; Você é quem conhece o ciclo de vida de seus objetos e pode dizer: "Nesse ponto, esse objeto deveria ter sido coletado; se não for, há algo errado".

Agora, se a contagem de "instâncias" para sua visualização descer para 0, não há vazamento lá. Se você acha que o aplicativo vazar, tente encontrar outros objetos que possam não ter sido descartados corretamente. Se a contagem permanecer em 1, significa que sua visão vazou. Agora, você terá que descobrir o porquê e onde.

Neste ponto, você deve tirar um "instantâneo da memória" (o botão ao lado do botão Force GC). Abra o instantâneo, encontre o objeto na grade e clique duas vezes nele. Isso fornecerá uma lista de todos os objetos que têm uma referência a esse objeto. Na verdade, é uma árvore, e provavelmente cada item conterá, por sua vez, uma série de referências de fundo e assim por diante. Estes são os objetos que estão impedindo que sua visão seja coletada. No painel direito, também, você terá um rastreamento de alocação. Isso mostrará como o objeto selecionado foi criado (como um rastreamento de pilha).

Você provavelmente verá um número de objetos Hugh lá. Mas sua melhor aposta é se concentrar naqueles que têm um ciclo de vida mais longo do que o objeto que você está examinando (sua visão). O que quero dizer é, procure o palco, uma visão dos pais, etc; Objetos dos quais sua visão depende, em vez de objetos que dependem da sua visão, se isso faz sentido. Se a sua visualização tiver um botão e você adicionou um ouvinte, seu botão terá um árbitro para sua visualização. Na maioria dos casos, isso não é um problema, já que o botão depende da visualização e, uma vez que a visualização é coletada, o mesmo ocorre com o botão. Portanto, a idéia é que, como existem muitos objetos, você deve tentar permanecer focado ou não chegará a lugar algum. Esse método é antes heurístico, mas na minha experiência, funciona.

Depois de encontrar a fonte de um vazamento, volte para a fonte, altere o código de acordo (talvez isso exija não apenas alterar o código, mas refatorar um pouco). Em seguida, repita o processo e verifique se sua alteração causou o efeito desejado. Pode demorar um pouco, dependendo de quão grande ou complexo é o seu aplicativo e quanto você sabe sobre ele. Mas se você for passo a passo, encontrando e corrigindo um problema na época, acabará se livrando dos vazamentos. Ou pelo menos os piores e mais evidentes. Então, embora um pouco tedioso, ele compensa (e como um bom lado, você acabar variável única, etc, etc; é uma experiência esclarecedora;).

Espero que isto ajude.

Outras dicas

O Flash GC usa uma mistura de contagem e varredura de ref, para detectar referências circulares. Parece que você está tendo outra referência em seu gráfico de objetos. O motivo mais comum é que os objetos que você deseja que ainda não estão sendo registrados em objetos em objetos que não estão descartados. Você pode tentar garantir que os manipuladores estejam sempre registrados com referência fraca. Você também pode substituir o AddEventListener e remover o Listener em todas as classes (base), se possível, procurar quais ouvintes estão registrados e se há chances de alguns não serem removidos.

Além disso, você pode escrever destruidores para seus objetos, que para os componentes da interface do usuário limpa gráficos e remover todas as crianças e, para todos os objetos, remove as referências a todas as propriedades. Dessa forma, apenas seu objeto é mantido na RAM, o que não deve exigir muita memória (uma pequena pegada de 20 b ou mais, mais 4 b por variável (8 para um número)).

greetz
back2dos

também uma heurística útil para encontrar vazamentos de memória: http://www.tikalk.com/flex/solving-memory-leaks-using-flash-builder-4-profiler

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top