O uso de memória relatado por Guppy difere do comando ps
-
20-09-2019 - |
Pergunta
Estou perfilando meu servidor torcido. Ele usa muito mais memória do que eu esperava. Seu uso de memória cresce com o tempo.
ps -o pid,rss,vsz,sz,size,command
PID RSS VSZ SZ SZ COMMAND
7697 70856 102176 25544 88320 twistd -y broadcast.tac
Como você pode ver, custa 102176 KBS, a saber, 99.78125 MBS. E eu uso o Guppy de um bueiro torcido para assistir ao perfil de uso da memória.
>>> hp.heap()
Partition of a set of 120537 objects. Total size = 10096636 bytes.
Index Count % Size % Cumulative % Kind (class / dict of class)
0 61145 51 5309736 53 5309736 53 str
1 27139 23 1031596 10 6341332 63 tuple
2 2138 2 541328 5 6882660 68 dict (no owner)
3 7190 6 488920 5 7371580 73 types.CodeType
4 325 0 436264 4 7807844 77 dict of module
5 7272 6 407232 4 8215076 81 function
6 574 0 305776 3 8520852 84 dict of class
7 605 1 263432 3 8784284 87 type
8 602 0 237200 2 9021484 89 dict of type
9 303 0 157560 2 9179044 91 dict of zope.interface.interface.Method
<384 more rows. Type e.g. '_.more' to view.>
Hum ... parece que há algo errado. Guppy mostra que o uso total da memória é 10096636 bytes, a saber, 9859.996 KBS ou 9.628 MBS.
Essa é uma enorme diferença. O que há de errado esse resultado estranho? O que estou fazendo errado?
Atualizar:Eu escrevi um script de monitor ontem à noite. Ele registra o uso da memória e o número de usuários on-line. É um servidor de rádio, para que você possa ver que há rádios e ouvintes totais. Aqui está a figura que eu gerei por matplotlib.
Algo é estranho. Às vezes, o uso de memória impresso por PS é muito baixo, assim
2010-01-15 00:46:05,139 INFO 4 4 17904 36732 9183 25944
2010-01-15 00:47:03,967 INFO 4 4 17916 36732 9183 25944
2010-01-15 00:48:04,373 INFO 4 4 17916 36732 9183 25944
2010-01-15 00:49:04,379 INFO 4 4 17916 36732 9183 25944
2010-01-15 00:50:02,989 INFO 4 4 3700 5256 1314 2260
Qual é o motivo do valor super baixo do uso da memória? E além do mais, mesmo não há rádios on-line, nem ouvintes, o uso da memória ainda é alto.
Solução
Possivelmente devido à troca/reserva de memória, com base na definição do PS:
RSS: resident set size, the non-swapped physical memory
that a task has used (in kiloBytes).
VSZ: virtual memory usage of entire process.
vm_lib + vm_exe + vm_data + vm_stack
Pode ser um pouco confuso, 4 métricas de tamanho diferentes podem ser vistas com:
# ps -eo pid,vsz,rss,sz,size,cmd|egrep python
PID VSZ RSS SZ SZ CMD
23801 4920 2896 1230 1100 python
O tamanho virtual inclui memória reservada pelo processo e não usada, o tamanho de todas as bibliotecas compartilhadas que foram carregadas, páginas que são trocadas e blocos que já foram libertados pelo seu processo, para que possa ser muito maior do que o tamanho de todos os objetos vivos em Python.
Algumas ferramentas adicionais para investigar o desempenho da memória:
Heay (parte de Guppy, que você está usando):http://guppy-pe.sourceforge.net/
Validador de memória Pythonhttp://www.softwareverify.com/python/memory/index.html
Pysizerhttp://pysizer.8325.org/
Bom guia sobre o rastreamento de vazamentos de memória em Python usando PDB e ObjGraph:
http://www.lshift.net/blog/2008/11/14/tracing-python-memory-leaks
Outras dicas
Como apontado acima do tamanho do RSS, é o que você está mais interessado aqui. O tamanho "virtual" inclui bibliotecas mapeadas, que você provavelmente não deseja contar.
Já faz um tempo desde que eu usei muito, mas tenho certeza de que as estatísticas que as impressões não incluem sobre a ponta adicionada pelo próprio Heapy. Essa sobrecarga pode ser bastante significativa (eu vi um processo RSS de 100 MB crescer mais uma dúzia ou mais MB, veja http://www.pkgcore.org/trac/pkgcore/doc/dev-notes/heapy.rst ).
Mas, no seu caso, suspeito que o problema é que você esteja usando uma biblioteca C que vaza ou usa a memória de uma maneira que Heay não rastreia. Heay está ciente da memória usada diretamente pelos objetos Python, mas se esses objetos embrulham objetos C que são alocados separadamente, normalmente não estiver ciente dessa memória. Você poderá adicionar suporte pesado às suas ligações (mas se você não controlar as ligações que usa, obviamente é um aborrecimento, e mesmo se você controlar as ligações, talvez não seja capaz de fazer isso, dependendo do que está envolvendo ).
Se houver vazamentos no nível C Heapy, também perderá o controle dessa memória (o tamanho do RSS aumentará, mas o tamanho relatado de Heapy permanecerá o mesmo). Valgrind é provavelmente sua melhor aposta para rastreá -los, assim como em outros aplicativos C.
Finalmente: A fragmentação da memória geralmente faz com que o uso da sua memória (como visto no topo) suba, mas não para baixo (muito). Geralmente, isso não é um grande problema com os daemons, pois o processo reutiliza essa memória, ele simplesmente não é lançado de volta ao sistema operacional; portanto, os valores no topo não retornam. Se o uso da memória (como visto por cima) subir mais ou menos linearmente com o número de usuários (conexões), não volta, mas também não continua crescendo para sempre até que você atinja um novo número máximo de usuários, a fragmentação provavelmente será culpar.
Esta não é uma resposta completa, mas no seu bueiro, eu também sugiro executar manualmente gc.collect () antes de procurar com PS ou top. Guppy mostrará a pilha alocada, mas não faz nada para liberar objetos proativamente que não são mais alocados.