/ / Comment améliorer les performances de python cgi qui lit un gros fichier et le retourne en téléchargement? - python, cgi, performance, mod-wsgi

Comment améliorer les performances de python cgi qui lit un gros fichier et le renvoie en téléchargement? - python, cgi, performance, mod-wsgi

J’ai ce script cgi python qui vérifie si on n’y a pas accédé plusieurs fois à partir de la même adresse IP et, si tout va bien, lit un gros disque sous forme de fichier (11 Mo), puis le renvoie sous forme de téléchargement.

Cela fonctionne, mais la performance est nulle. Le goulot d'étranglement semble lire cet énorme fichier à plusieurs reprises:

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)

Comment puis-je rendre cela plus rapide? J'ai pensé à utiliser un disque virtuel pour conserver le fichier, mais il doit y avoir une meilleure solution. En utilisant mod_wsgi au lieu d'un script cgi aide? Serais-je capable de conserver le gros fichier dans la mémoire d’apache?

Toute aide est grandement appréciée.

Réponses:

9 pour la réponse № 1

Utilisez mod_wsgi et utilisez quelque chose qui ressemble à:

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 d'autres termes, utilisez wsgi.file_wrapper extension du standard WSGI pour permettre à Apache / mod_wsgi d’effectuer une réponse optimisée du contenu du fichier à l’aide de sendfile / mmap. En d'autres termes, votre application n'a même pas besoin de lire le fichier en mémoire.


2 pour la réponse № 2

Pourquoi imprimez-vous en une seule impressiondéclaration? Python doit générer plusieurs chaînes temporaires pour gérer les en-têtes de contenu et, à cause de ce dernier% s, il doit contenir tout le contenu du fichier dans deux vars de chaînes différents. Cela devrait être mieux.

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

Vous pouvez également envisager de lire le fichier à l'aide du module IO brut afin que Python ne crée pas de tampons temporaires que vous n'utilisez pas.


1 pour la réponse № 3

mod_wsgi ou FastCGI serait utile dans le sens oùvous n'avez pas besoin de recharger l'interpréteur Python à chaque fois que votre script est exécuté. Toutefois, ils ne feront que peu pour améliorer les performances de lecture du fichier (si c'est vraiment votre goulot d'étranglement). Je vous conseillerais plutôt d’utiliser quelque chose d’autre part.


1 pour la réponse № 4

Essayez de lire et d’afficher (c’est-à-dire mettre en mémoire tampon) un bloc de 16 Ko à la fois. Python est probablement en train de faire quelque chose de lent en arrière-plan et la mise en mémoire tampon manuelle peut être plus rapide.

Vous ne devriez pas "utiliser, par exemple, un disque virtuel - le cache du disque du système d'exploitation devrait mettre en cache le contenu du fichier pour vous.