Django Apps - Do Núcleo a Otimização

1,983 views

Published on

Como utilizar Profilers para analisar Apps Django. Quando necessário otimizar a performance de uma App, é importante saber onde otimizar, não dispendando tempo para otimizar funções raramente usadas ou que não sejam o real problema, é preciso saber em que parte do programa a maior parte do tempo é gasto.

Published in: Technology

Django Apps - Do Núcleo a Otimização

  1. 1. DJango APPS Do Núcleo a Otimização Leandro Zanuz (lzanuz@ucs.br)
  2. 2. Desenvolvendo apps...Desenvolvendo apps...  A aplicação está pronta, tudo funcionando, mas a performance de algumas views está ruim, e agora?  É importante ter algo que possa mostrar a execução da view, acessos realizados ao BD, memcache e coisas do tipo, de forma que se possa entender seu funcionamento e realizar as otimizações necessárias.
  3. 3. O que fazer...O que fazer...  Saber onde otimizar, não dispendando tempo para otimizar funções raramente usadas ou que não sejam o real problema, é preciso saber em que parte do programa a maior parte do tempo é gasto.  Identificar os pontos de estrangulamento;  Melhorar a performance do programa ou diminuir sua utilização de memória (ou às vezes ambos).
  4. 4. Como fazer...Como fazer...  Registrar as solicitações e seus tempos tornando possível visualizar o tempo médio que uma determinada solicitação tomou.  Registrar todas as ações do programa (chamadas de funções, acessos a bases de dados, acessos a webservices, etc.)  Analisar os tempos coletados de maneira informativa e de possível classificação.
  5. 5. O que utilizar...O que utilizar...  Profilers são programas que monitoram o tempo e a performance de execução de um programa;  Investigam a execução de um programa e recolhem informações para análise crítica;  Fornecem indicadores de onde o tempo está sendo gasto durante sua execução.
  6. 6. Python profilers...Python profilers...  cProfile: escrito em C; baixo overhead; ideal para programas extensos; disponível a partir da versão 2.5.  hotshot: escrito em C; foco em minimizar o tempo de overhead; a algum tempo não é atualizado; possibilidade de exclusão em futuras versões do Python.
  7. 7. Profiling Django apps...Profiling Django apps...  Possibilidade de análisar qualquer URL adicionando um parâmetro ao GET: ?PROF; http://meusite.com.br/projeto/?PROF  Inclusão de um middleware para inspeção da requisição, o qual instancia um objeto profile e analisa sua execução;  O resultado é exibido no browser;  Se PROF não estiver nos parâmetros GET, a execução ocorrerá normalmente.
  8. 8. Middleware...Middleware... import sys try: import cProfile as profile except ImportError: import profile try: from cStringIO import StringIO except ImportError: import StringIO from django.conf import settings class ProfilerMiddleware(object): def can(self, request): return settings.PROFILING and 'PROF' in request.GET and (not settings.INTERNAL_IPS or request.META['REMOTE_ADDR'] in settings.INTERNAL_IPS) def process_view(self, request, callback, callback_args, callback_kwargs): if self.can(request): self.profiler = profile.Profile() args = (request,) + callback_args return self.profiler.runcall(callback, *args, **callback_kwargs) def process_response(self, request, response): if self.can(request): self.profiler.create_stats() out = StringIO() old_stdout, sys.stdout = sys.stdout, out self.profiler.print_stats(1) sys.stdout = old_stdout response.content = '<pre>%s</pre>' % out.getvalue() return response http://www.pastethat.com/dlnsr
  9. 9. Middleware...Middleware... from django.db import connection class DatabaseProfilerMiddleware(object): def can(self, request): return settings.DEBUG and 'DPROF' in request.GET and (not settings.INTERNAL_IPS or request.META['REMOTE_ADDR'] in settings.INTERNAL_IPS) def process_request(self, request): if self.can(request): self.DEBUG = settings.DEBUG settings.DEBUG = True def process_response(self, request, response): if self.can(request): out = StringIO() out.write('timetsqln') total_time = 0 for query in reversed(sorted(connection.queries, key=lambda x: x['time'])): total_time += float(query['time'])*1000 out.write('%st%sn' % (query['time'], query['sql'])) response.content = '<pre style="white-space:pre-wrap">%d queries executed in %.3f secondsnn%s</pre>' % (len(connection.queries), total_time/1000, out.getvalue()) settings.DEBUG = self.DEBUG return response http://www.pastethat.com/dlnsr
  10. 10. MIDDLEWARE_CLASSES = ( ... 'apps.ProfilerMiddleware', 'apps.DatabaseProfilerMiddleware', ... ) Django Settings...Django Settings...
  11. 11. 19743 function calls (19238 primitive calls) in 0.064 CPU seconds Ordered by: internal time ncalls tottime percall cumtime percall filename:lineno(function) 2 0.025 0.013 0.026 0.013 calculo.py:4(calculo_m2) 1 0.001 0.001 0.002 0.002 connections.py:44(__init__) 243 0.001 0.000 0.001 0.000 {isinstance} 24/8 0.001 0.000 0.002 0.000 copy.py:144(deepcopy) 3/1 0.000 0.000 0.003 0.003 __init__.py:256(parse) 6 0.000 0.000 0.001 0.000 __init__.py:501(__init__) 29 0.000 0.000 0.001 0.000 encoding.py:59(force_unicode) 1 0.000 0.000 0.001 0.001 debug.py:10(tokenize) ... ncalls: número de chamadas tottime: tempo total gasto na função (excluindo o tempo gasto em chamadas as sub-funções) percall: quociente de tottime por ncalls cumtime: tempo total gasto na função e todas as sub-funções (desde a invocação até ao retorno) percall: quociente de percall por ncalls filename lineno(function): referência à função Profiler log...Profiler log...
  12. 12. Kcachegrind...Kcachegrind...  Kcachegrind é uma aplicação KDE que possibilita uma melhor interpretação e análise dos resultados;  Para transformar os resultados coletados pelo hotshot compatíveis ao Kcachegrind pode utilizar o hotshot2calltree. apt-get install kcachegrind-converters hotshot2calltree arquivo.prof > cachegrind.out  Para converter logs do cProfile pode-se utilizar o script: http://www.gnome.org/~johan/lsprofcalltree.py
  13. 13. Resultado no Kcachegrind...Resultado no Kcachegrind...
  14. 14. Leandro Zanuz lzanuz@ucs.br Perguntas?Perguntas?

×