/ / ¿Cómo mejorar el rendimiento de python cgi que lee un archivo grande y lo devuelve como una descarga? - python, cgi, performance, mod-wsgi

¿Cómo mejorar el rendimiento de python cgi que lee un archivo grande y lo devuelve como descarga? - python, cgi, performance, mod-wsgi

Tengo esta secuencia de comandos de python cgi que verifica si no se ha accedido muchas veces desde la misma IP, y si todo está bien, lee un disco de formato de archivo grande (11 MB) y luego lo devuelve como una descarga.

Funciona, pero el rendimiento apesta. El cuello de botella parece estar leyendo este enorme archivo una y otra vez:

def download_demo():
"""
Returns the demo file
"""

file = open(FILENAME, "r")
buff = file.read()

print "Content-Type:application/x-downloadnContent-Disposition:attachment;filename=%snContent-Length:%snn%s" %    (os.path.split(FILENAME)[-1], len(buff), buff)

¿Cómo puedo hacer esto más rápido? Pensé en usar un disco RAM para guardar el archivo, pero debe haber una solución mejor. Usaría mod_wsgi En lugar de una ayuda de script cgi? ¿Sería capaz de mantener el archivo grande en el espacio de memoria de Apache?

Cualquier ayuda es muy apreciada.

Respuestas

9 para la respuesta № 1

Use mod_wsgi y use algo similar a:

def application(environ, start_response):
status = "200 OK"
output = "Hello World!"

response_headers = [("Content-type", "text/plain")]
start_response(status, response_headers)

file = open("/usr/share/dict/words", "rb")
return environ["wsgi.file_wrapper"](file)

En otras palabras, use wsgi.extensión file_wrapper del estándar WSGI para permitir que Apache / mod_wsgi realice una respuesta optimizada de los contenidos del archivo utilizando sendfile / mmap. En otras palabras, evita que la aplicación necesite leer el archivo en la memoria.


2 para la respuesta № 2

¿Por qué estás imprimiendo todo en una sola impresión?¿declaración? Python tiene que generar varias cadenas temporales para manejar los encabezados de contenido y, debido a ese último% s, debe mantener todo el contenido del archivo en dos cadenas de caracteres diferentes. Esto debería ser mejor.

print "Content-Type:application/x-downloadnContent-Disposition:attachment;filename=%snContent-Length:%snn" %    (os.path.split(FILENAME)[-1], len(buff))
print buff

También puede considerar leer el archivo utilizando el módulo de E / S sin formato para que Python no cree los buffers temporales que no está utilizando.


1 para la respuesta № 3

Mod_wsgi o FastCGI ayudaría en el sentido de queno necesita volver a cargar el intérprete de Python cada vez que se ejecute su script. Sin embargo, no harán mucho por mejorar el rendimiento de la lectura del archivo (si eso es lo que realmente es su cuello de botella). Te aconsejaría que uses algo similar a memcached.


1 para la respuesta № 4

Intente leer y emitir (es decir, almacenar en búfer) una parte de, por ejemplo, 16 KB a la vez. Probablemente Python está haciendo algo lento detrás de escena y el almacenamiento en búfer manual puede ser más rápido.

No debería tener que usar, por ejemplo, un disco RAM: el caché del disco del sistema operativo debería almacenar el contenido del archivo por usted.