On dit que Python gère automatiquement la mémoire. Je suis confus parce que j'ai un programme Python utilise toujours plus de 2 Go de mémoire.
C'est un simple téléchargeur de données binaires multi-threads et déballeur. P>
MemTotal: 7975216 kB MemFree: 732368 kB Buffers: 38032 kB Cached: 4365664 kB SwapCached: 14016 kB Active: 2182264 kB Inactive: 4836612 kB
8 Réponses :
Vous pouvez rendre ce programme plus efficace de la mémoire en ne lisant pas les 15 Mo de la connexion TCP, mais le traitement de chaque ligne telle qu'elle est lue. Cela permettra aux serveurs distants vous attendez, bien sûr, mais ça va. p>
Python n'est tout simplement pas très efficace de la mémoire. Il n'a pas été construit pour ça. P>
La dernière ligne devrait sûrement être f.close () code>? Ces parens suivants sont un peu importants. p>
Oui, c'est f.close (). C'était une faute de frappe en poste d'origine.
Vous pouvez faire plus de votre travail dans le code C compilé si vous convertissez cela en une compréhension de la liste: à: p> Ceci est en fait légèrement différent de votre code d'origine. Dans votre version, GetData retourne un 3 tuple, qui revient dans des articles. Vous pouvez ensuite itérer sur ce triplet et appendez ';'. Joindre (article) pour chaque élément dedans. Cela signifie que vous obtenez 3 entrées ajoutées aux données de chaque triplet en lecture de GetData, chacun ';'. Join. Si les éléments ne sont que des chaînes, alors ';'. Joindre vous donnera une corde avec tous les autres personnages A '; - c'est ';'. Joindre ("ABC") redonnera "A; B; C". Je pense que ce que vous avez réellement em> voulait que chaque triplet soit enregistré à la liste des données comme les 3 valeurs du triplet, séparées par des points-virgules. C'est ce que ma version génère. P> Cela peut également aider quelque peu avec votre problème de mémoire d'origine, car vous ne créez plus autant de valeurs Python. N'oubliez pas qu'une variable de python a beaucoup em> plus de frais généraux d'un dans une langue telle que C. Étant donné que chaque valeur est elle-même un objet et ajoutez la surcharge de chaque nom de référence à cet objet, vous pouvez facilement développer le Condition de stockage théorique plusieurs fois. Dans votre cas, la lecture de 15 Mo x 15 = 225Mb + la surcharge de chaque élément de chaque triple étant stockée sous forme d'une entrée de chaîne dans votre liste de données pourrait rapidement se développer à votre taille observée de 2 Go. Au minimum, ma version de votre liste de données n'aura que 1/3 des entrées, ainsi que les références d'élément distinctes sont ignorées, plus l'itération est effectuée dans le code compilé. P> P>
envisagez d'utiliser xRange () au lieu de la plage (), je crois que Xrange est un générateur tandis que la plage () étend toute la liste.
Je dirais soit de ne pas lire le fichier entier dans la mémoire, ou Don 'T Gardez toute la structure déballée en mémoire. P>
Actuellement, vous gardez à la fois en mémoire, en même temps, cela va être assez grand. Donc, vous avez donc au moins deux copies de vos données en mémoire, plus des métadonnées. P>
aussi la ligne finale p> peut vraiment dire que vous ". VE obtenu temporairement une troisième copie en mémoire (une grosse chaîne avec tout le fichier de sortie). p> Donc, je dirais que vous le faites de manière assez inefficace, en conservant l'intégralité du fichier d'entrée, une sortie complète Fichier et une bonne quantité de données intermédiaires en mémoire à la fois. p> Utiliser le générateur pour analyser, c'est une bonne idée. Envisagez d'écrire chaque enregistrement après que vous l'avez généré (il peut ensuite être jeté et la mémoire réutilisée), ou si cela provoque trop de demandes d'écriture, datez-les, disons, 100 rangées à la fois. P> De même, la lecture de la réponse pourrait être faite en morceaux. Comme ils sont corrigés des enregistrements, cela devrait être raisonnablement facile. P> P>
Le principal coupable ici est tel que mentionné ci-dessus de l'appel de la plage (). Il créera une liste avec 15 millions de membres et cela mangera 200 MB de votre mémoire et avec 15 processus, c'est 3 Go. P>
Mais ne lisez pas non plus dans l'ensemble du fichier de 15 Mo dans des données (), de lecture bit à partir de la réponse. Coller ces 15 Mo dans une variable utilisera plus de 15 Mo de mémoire plus que de lire le bit de la réponse de la réponse. P>
Vous voudrez peut-être envisager simplement d'extraire simplement des données jusqu'à ce que vous épuisez si indata et de comparer le nombre de données que vous avez extraites avec ce que les premiers octets ont dit que cela devrait être. Ensuite, vous n'avez besoin ni gamme () ni xrange (). Semble plus pythonique pour moi. :) p>
En fait, le nombre variable ici n'est pas de près de 15 millions de gamme car chaque morceau de données binaires est de 30 octets. Il ne créera donc pas une liste avec 15 millions d'éléments.
Ah, je vois. Pourtant, cela aidera autant que de ne pas lire dans toutes les données dans données code>, puis.
Il y a 2 endroits évidents où vous gardez de gros objets de données en mémoire ( Ces modifications vous sauveront beaucoup de mémoire . p> p> Data Code> variable dans
getdata () code> et
data code> dans
Mythead.run () code> - ces deux prendront environ 500 Mo) et il y a probablement d'autres endroits dans le code sauté. Il est à la fois facile de rendre la mémoire efficace. Utilisez
réponse.read (4) code> au lieu de lire une réponse entière à la fois et faites-la de la même manière dans le code derrière
Déballez la longueur fixe des données binaires ici code>. Changer
data.append (...) code> dans
mythread.run () code> à
Assurez-vous de supprimer les threads après leur arrêt. (en utilisant del code>) p>
Comme les autres l'ont dit, vous avez besoin d'au moins les deux modifications suivantes:
Ne crée pas une énorme liste d'entiers avec ne crée pas de chaîne énorme en tant que corps de fichier complet à écrire à la fois p>
Encore meilleur, vous pouvez écrire le fichier comme: p> plage code> p>
La première question serait la suivante: combien de mémoire physique avez-vous disponible? Pourrait simplement être que Python décide qu'il ne vaut pas la peine de se nettoyer car il y a encore 1 Go de mémoire physique gratuite de toute façon.
Essayez Utilisation de la mémoire de profilage: Stackoverflow.com/questions/110259/python-Memory-Profiler
@Matthew, on dirait que 730 Mo de RAM de 8 Go sont disponibles.
Essayez de frayer 15 processus à la place - combien de mémoire consommez-vous de cette manière? Je devine beaucoup moins, et je suppose que le vrai coupable est le truc de threading (j'ai écrit un serveur TCP Echo très simple à l'aide de multithreading qui a pris 100% de CPU après 2 heures d'exécution - fixée avec torsadée, jamais la peine de regarder dans le filetage. manque de performance).