Django (?) Realmente lento con grandes conjuntos de datos después de hacer un perfil de python
Estaba comparando un antiguo script PHP en comparación con la versión más nueva y elegante de Django y la de PHP, con un escupido completo de HTML y todo funcionaba más rápido. Mucho más rápido hasta el punto de que algo tiene que estar mal en el Django.
Primero, algo de contexto: tengo una página que distribuye informes de datos de ventas. Los datos se pueden filtrar por varias cosas, pero en su mayoría se filtran por fecha. Esto hace que sea un poco difícil almacenarlo en caché ya que las posibilidades de resultados son casi infinitas. Hay muchos números y cálculos realizados, pero nunca fue un problema manejar dentro de PHP.
ACTUALIZACIONES:
Después de algunas pruebas adicionales, no hay nada en mi opinión que esté causando la desaceleración. Si simplemente hago un cálculo numérico de los datos y escupo 5 filas de HTML renderizado, no es tan lento (aún más lento que PHP), pero si estoy generando una gran cantidad de datos, es MUY lento.
Cada vez que ejecuté un informe grande (por ejemplo, todas las ventas del año), el uso de la CPU de la máquina es del 100%. No sé si esto significa mucho. Estoy usando mod_python y Apache. Tal vez el cambio a WSGI puede ayudar?
Las etiquetas de mi plantilla que muestran los subtotales / totales se procesan en cualquier lugar desde 0,1 segundos hasta 1 segundo para conjuntos realmente grandes. Los llamo aproximadamente 6 veces en el informe para que no parezcan ser el mayor problema.
Ahora, ejecuté un perfilador de Python y regresé con estos resultados:
Ordered by: internal time List reduced from 3074 to 20 due to restriction ncalls tottime percall cumtime percall filename:lineno(function) 2939417 26.290 0.000 44.857 0.000 /usr/lib/python2.5/tokenize.py:212(generate_tokens) 2822655 17.049 0.000 17.049 0.000 {built-in method match} 1689928 15.418 0.000 23.297 0.000 /usr/lib/python2.5/decimal.py:515(__new__) 12289605 11.464 0.000 11.464 0.000 {isinstance} 882618 9.614 0.000 25.518 0.000 /usr/lib/python2.5/decimal.py:1447(_fix) 17393 8.742 0.001 60.798 0.003 /usr/lib/python2.5/tokenize.py:158(tokenize_loop) 11 7.886 0.717 7.886 0.717 {method 'accept' of '_socket.socket' objects} 365577 7.854 0.000 30.233 0.000 /usr/lib/python2.5/decimal.py:954(__add__) 2922024 7.199 0.000 7.199 0.000 /usr/lib/python2.5/inspect.py:571(tokeneater) 438750 5.868 0.000 31.033 0.000 /usr/lib/python2.5/decimal.py:1064(__mul__) 60799 5.666 0.000 9.377 0.000 /usr/lib/python2.5/site-packages/django/db/models/base.py:241(__init__) 17393 4.734 0.000 4.734 0.000 {method 'query' of '_mysql.connection' objects} 1124348 4.631 0.000 8.469 0.000 /usr/lib/python2.5/site-packages/django/utils/encoding.py:44(force_unicode) 219076 4.139 0.000 156.618 0.001 /usr/lib/python2.5/site-packages/django/template/__init__.py:700(_resolve_lookup) 1074478 3.690 0.000 11.096 0.000 /usr/lib/python2.5/decimal.py:5065(_convert_other) 2973281 3.424 0.000 3.424 0.000 /usr/lib/python2.5/decimal.py:718(__nonzero__) 759014 2.962 0.000 3.371 0.000 /usr/lib/python2.5/decimal.py:4675(__init__) 381756 2.806 0.000 128.447 0.000 /usr/lib/python2.5/site-packages/django/db/models/fields/related.py:231(__get__) 842130 2.764 0.000 3.557 0.000 /usr/lib/python2.5/decimal.py:3339(_dec_from_triple)
tokenize.py aparece en la parte superior, lo que puede tener algún sentido ya que estoy haciendo mucho formato de números. Decimal.py tiene sentido ya que el informe es esencialmente un 90% de los números. No tengo ni idea de cuál es el método incorporado.match
es como no estoy haciendo ningún Regex o similar en mi propio código (¿Algo que está haciendo Django?) Lo más cercano es que estoy usando itertools ifilter.
Parece que esos son los principales culpables y si pudiera averiguar cómo reducir el tiempo de procesamiento de esos, entonces tendría una página mucho más rápida.
¿Alguien tiene alguna sugerencia sobre cómo podría comenzar a reducir esto? Realmente no sé cómo arreglaría esto los problemas de tokenize / decimal sin simplemente eliminarlos.
Actualización: realicé algunas pruebas con / sin filtros en la mayoría de los datos y los tiempos de resultados prácticamente volvieron a ser lo mismo, siendo este último un poco más rápido pero no mucho para ser la causa del problema. ¿Qué está pasando exactamente en tokenize.py?