Pergunta

O meu problema é:

Eu tenho um script Perl que usa muita memória (comportamento esperado por causa do cache). Mas, percebi que quanto mais eu faço caching, mais lento ele fica eo processo passa a maior parte do tempo no modo sleep.

Eu pensei pré-alocação de memória para o processo pode acelerar o desempenho.

Alguém tem alguma idéia aqui?

Atualizar :

Eu acho que eu não estou sendo muito claro aqui. Porei questão de forma mais clara:

Eu não estou procurando os caminhos da pré-alocação de dentro do script Perl. Eu não acho que iria me ajudar muito aqui. O que eu estou no interessada é uma maneira de dizer OS para alocar uma quantidade X de memória para o meu script Perl para que ele não tem que competir com outros processos chegando mais tarde.

Suponha que eu não posso fugir com o uso de memória. Embora, eu estou explorando maneiras de reduzir isso também, mas não espere muita melhoria lá. FYI, eu estou trabalhando em um Solaris 10 máquina.

Foi útil?

Solução

O que eu recolhidas a partir de sua postagem e os comentários é esta:

  • O seu programa fica lento quando o uso de memória aumenta
  • O seu pogram passa cada vez mais tempo de sono, não se computando.

A maioria dos eplanation prováveis: Sleeping meio à espera de um recurso se torne disponível. Neste caso, o recurso mais provável é a memória. Use o comando vmstat 1 para verificar. Ter um olhar para a coluna sr. Se ele vai além ~ 150 consistentemente o sistema está desesperado para páginas livres para satisfazer a demanda. Isto é acompanhado por uma elevada actividade da pi, po e colunas fr.

Se este é de fato o caso, as melhores opções são:

  • memória de sistema de atualização para atender a demanda
  • Reduza o uso de memória para um apropriado nível para o sistema em questão.

memória preallocating não vai ajudar. Em ambos os casos a demanda de memória irá exceder a memória principal disponível em algum ponto. O kernel então terá de decidir quais as páginas que precisa estar na memória agora e que páginas podem ser apagadas e reutilizadas para as páginas mais necessários urgentemente. Se todas as páginas regularily necessários (o conjunto de trabalho) excede o tamanho da memória principal, o sistema está em constante movimento páginas de e para o armazenamento secundário (swap). O sistema é então diz-se debatendo e não gasta muito tempo fazendo um trabalho útil. Não há nada que você possa fazer sobre isso execept adicionar memória ou usando menos.

Outras dicas

A partir de um comentário:

As limitações de memória não são muito graves, mas o consumo de memória cresce facilmente a GBs e quando temos processos competindo para memória, ele fica muito lento. Quero reservar alguma memória de OS para que surra é mínima, mesmo quando muitos outros processos vir. Jagmal

Vamos dar um rumo diferente então. O problema não é realmente com o seu script Perl em particular. Em vez disso, todos os processos na máquina estão consumindo muita memória para a máquina a alça conforme configurado.

Você pode memória "reserva", mas isso não vai impedir a goleada. Na verdade, ele poderia tornar o problema pior porque o sistema operacional não vai saber se você está usando a memória ou simplesmente guardá-lo para mais tarde.

Eu suspeito que você está sofrendo a tragédia dos comuns . Estou certo de que muitos outros usuários estão na máquina em questão? Se assim for, este é mais um problema social do que um problema técnico. O que você precisa é de alguém (provavelmente o administrador do sistema) para intervir e coordenar todos os processos na máquina. Eles devem encontrar a maioria dos porcos de memória extravagante e trabalhar com seus programadores para reduzir o custo dos recursos do sistema. Além disso, eles devem organizar processos de ser agendada para que a alocação de recursos é eficiente. Finalmente, eles podem precisar de obter mais ou melhorada hardware para lidar com a carga do sistema esperado.

Algumas perguntas que você pode perguntar-se:

  • são as minhas estruturas de dados realmente útil para a tarefa em mãos?
  • que eu realmente têm de cache que muito?
  • posso jogar fora de dados em cache depois de algum tempo?
my @array;
$#array = 1_000_000; # pre-extend array to one million elements,
                     # http://perldoc.perl.org/perldata.html#Scalar-values

my %hash;
keys(%hash) = 8192; # pre-allocate hash buckets 
                    # (same documentation section)

Não estar familiarizado com o seu código, eu vou arriscar alguma especulação selvagem aqui [sorriso] que essas técnicas não vão oferecer novas grandes eficiências ao seu script, mas que a pré-alocação poderia ajudar um pouco.

Boa sorte!

- Douglas Hunter

Recentemente redescobriu uma excelente Randal L. Schwartz artigo que inclui preallocating uma matriz. Assumindo que este é o seu problema, você pode testar preallocating com uma variação sobre esse código. Mas certifique-se de testar o resultado.

A razão o script fica mais lento com mais cache pode ser surra . Presumivelmente, a razão para o cache em primeiro lugar é para aumentar o desempenho. Assim, uma resposta rápida é:. Reduzir cache

Agora, pode haver maneiras de modificar seu esquema de cache para que ele usa menos memória principal e evita goleada. Por exemplo, você pode achar que cache para um arquivo ou banco de dados em vez de para a memória pode melhorar o desempenho. Descobri que sistema de arquivos e cache de banco de dados pode ser mais eficiente que o cache de aplicativo e pode ser compartilhada entre várias instâncias.

Outra idéia poderia ser a de alterar o seu algoritmo para reduzir o uso de memória em outras áreas. Por exemplo, em vez de puxar um arquivo inteiro na memória, programas Perl tendem a trabalhar melhor ler linha por linha.

Finalmente, você já explorou o Memoize módulo ? Pode não ser imediatamente aplicável, mas poderia ser uma fonte de ideias.

Eu não poderia encontrar uma maneira de fazer isso ainda.

Mas, eu descobri que (Veja este para detalhes)

A memória alocada para lexicals (ou seja, my () variáveis) não pode ser recuperado ou reutilizados mesmo que ir fora do escopo. É reservado no caso das variáveis voltar para o escopo. memória alocada a variáveis ??globais podem ser reutilizados (Dentro de seu programa) usando undef () ing e / ou apagar ().

Então, eu acredito que uma possibilidade aqui poderia ser para verificar se eu posso reduzir a impressão de memória total de variáveis ??lexicais em um determinado ponto no tempo.

Parece que você está procurando limite ou ulimit . Mas eu suspeito que fará com que um script que vai além do limite a falhar, o que provavelmente não é o que você quer.

Uma idéia melhor poderia ser a de compartilhar dados em cache entre processos. Colocar dados em um banco de dados ou em um arquivo funciona bem em minha experiência.

Eu odeio dizer isso, mas se suas limitações de memória são deste grave, Perl não é provavelmente a linguagem certa para esta aplicação. C seria uma escolha melhor, eu acho.

Uma coisa que você poderia fazer é zonas de uso Solaris (recipientes).
Você poderia colocar o seu processo em uma zona e alocá-lo recursos como memória RAM e CPU.
Aqui estão dois links para alguns tutoriais:

  1. Solaris Containers Como guia para
  2. controle de recursos Zona do Solaris 10 08/07 OS

Embora não seja pré-alocação de como você pediu, você também pode querer olhar para as grandes opções de tamanho de página, de modo que quando perl tem de pedir ao sistema operacional para mais memória para o seu programa, ele recebe-lo em pedaços maiores.

Consulte Solaris Internals: Múltiplas páginas Tamanho Apoio para obter mais informações sobre o diferença que isso faz e como fazê-lo.

http://metacpan.org/pod/Devel::Size

Você poderia também em linha uma função c para fazer o acima.

Tanto quanto eu sei, você não pode alocar memória diretamente do Perl. Você pode contornar isso escrevendo um módulo XS, ou usando uma função C em linha como eu mencionei.

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