Como posso configurar o Primavera para salvar tanta memória quanto possível?
-
20-08-2019 - |
Pergunta
Estamos implantando um aplicativo em um dispositivo semi-incorporado que tem restrições de memória. Olhando para poupar tudo o que podemos estamos analisando heap dumps do aplicativo e atacando os maiores consumidores.
Nós usamos Spring 2.5 em conjunto com a Primavera DM 1.1 e notamos que alguns dos nossos pacotes com contextos Primavera mais complexas estão usando-se um pouco de memória desde a Primavera parece manter ao redor do gráfico de objeto inteiro contendo todos os BeanDefinitions que foram analisados a partir do XML. Eu diria que a maior parte isso é desnecessário uma vez que o aplicativo foi inicializado e tudo é injetado.
Existem opções de configuração para a Primavera que permitem controlar este comportamento? Executar em algum modo de baixa memória? Jogue fora todas as coisas desnecessárias? Trade tempo de computação para o tamanho?
Solução
Eu tive membros da equipe têm um olhar mais profundo para isso e tive alguns resultados interessantes. Primavera em sua configuração padrão muito não está interessado em ser especialmente conservador em seu uso de memória. Há 2 aspectos básicos que podem ser otimizadas para ganhos significativos:
- O primeiro é uma propriedade não-expostos dentro do
OsgiBundleXmlApplicationContext
Primavera que você pode substituir se você estender a partir dessa classe e substituir o métodocustomizeBeanFactory
.
Nós fizemos assim:
@Override
protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) {
super.customizeBeanFactory(beanFactory);
String cacheBeanMetadataSysProp = System.getProperty(CACHE_BEAN_METADATA, "true");
if (cacheBeanMetadataSysProp != null
&& cacheBeanMetadataSysProp.equalsIgnoreCase("false")) {
beanFactory.setCacheBeanMetadata(false);
} else if (cacheBeanMetadataSysProp != null
&& cacheBeanMetadataSysProp.equalsIgnoreCase("true")) {
beanFactory.setCacheBeanMetadata(true);
}
}
A configuração da propriedade "setCacheBeanMetadata" para false
faz com que o BeanDefinitions
(basicamente o espelho programático da configuração baseada em XML) para ser descartado após a inicialização.
- A segunda mudança - que atualmente temos um protótipo para - É um remendo para o código-fonte da Primavera para fazer a inicialização lenta de coleções. Acontece que muitos objetos mola interna que representam Feijão e todas as suas propriedades têm um monte de membros que são inicializados para HashMaps e outras coleções por padrão, mas muito raramente são preenchidos com dados. Alterar o framework Spring para inicializar estes preguiçosamente vai salvar outra quantidade significativa de memória, mas é uma mudança muito mais invasivo.
Outras dicas
Você pode salvar alguma memória com um BeanFactory - veja 3.8.1. BeanFactory ou ApplicationContext :
Como o ApplicationContext inclui todas as funcionalidades do BeanFactory, é geralmente recomendado que seja usado em preferência ao BeanFactory, exceto por algumas situações limitadas, como em um applet, onde o consumo de memória pode ser crítico e alguns kilobytes extras pode fazer a diferença.
Eu não estou ciente de qualquer maneira de fazer Primavera executar no modo "luz". Você poderia tentar implementar um BeanFactoryPostProcessor e usá-lo para remover certos grãos a partir do contexto. Eu não tenho idéia se isso vai levar a erros de mola interna no entanto.
Se você só pode usar Primavera na inicialização, ie todos os grãos estão ligados e, em seguida, você não precisa o contexto do aplicativo ou a lógica de desligamento, você pode começar seu aplicativo e em seguida, desmarque todas as referências ao contexto de aplicação.
Se a sua configuração do Spring usa AOP e carga tecelagem tempo, você poderia usar aop.xml para recuperar alguma memória de AspectJ usando o recurso de tipo rebaixamento AspectJ que foi introduzida no 1.6.5.
<weaver options="-Xset:typeDemotion=true"/>
Analise o seu montão, se você encontrar muitos objetos RefType, o truque acima vai ajudar.