2012-08-14 14 views
6

Ho uno script molto semplice che alloca la memoria, dels l'unico riferimento a un oggetto di dimensioni considerevoli, mentre stampa i report heapy e pidstat. Dopo aver eseguito lo script, Heapy mi dice che non ci dovrebbe essere molta memoria utilizzata mentre pidstat mi dice il contrario:python - la memoria non viene restituita al kernel

from guppy import hpy 
import time 
import sys 
import os 

''' 
1) print heapy and pidstat report after starting and before actually doing any work 
2) allocate some memory in a simple 2d array 
3) print heapy and pidstat report 
4) del the d2 array (attempt at garbage collection) 
5) print heapy and pidstat report 
6) sleep so pidstat can continue to be run to check on memory 
''' 

def pidstat(msg): 
    print '===============================' 
    print msg 
    os.system('pidstat -r -p %s' % os.getpid()) 
    print '+++++++++++++++++++++++++++++++' 
    print hpy().heap()[0] 
    print '===============================' 

pidstat('before doing anything') 
docs = [] 
for doc in range(0, 10000): 
    docs.append([j for j in range(0, 1000)]) 

pidstat('after fetching all the docs into memory') 
del docs 

pidstat('after freeing the docs') 
time.sleep(60) 

L'output è il seguente:

 
=============================== 
before doing anything 
Linux 2.6.38-15-generic (hersheezy)  08/14/2012 _x86_64_ (4 CPU) 

01:05:20 PM  PID minflt/s majflt/s  VSZ RSS %MEM Command 
01:05:20 PM  5360  0.44  0.00 44768 9180 0.11 python 
+++++++++++++++++++++++++++++++ 
Partition of a set of 19760 objects. Total size = 1591024 bytes. 
Index Count %  Size % Cumulative % Kind (class/dict of class) 
    0 19760 100 1591024 100 1591024 100 str 
=============================== 
=============================== 
after fetching all the docs into memory 
Linux 2.6.38-15-generic (hersheezy)  08/14/2012 _x86_64_ (4 CPU) 

01:05:21 PM  PID minflt/s majflt/s  VSZ RSS %MEM Command 
01:05:21 PM  5360  8.95  0.00 318656 279120 3.49 python 
+++++++++++++++++++++++++++++++ 
Partition of a set of 7431665 objects. Total size = 178359960 bytes. 
Index Count %  Size % Cumulative % Kind (class/dict of class) 
    0 7431665 100 178359960 100 178359960 100 int 
=============================== 
=============================== 
after freeing the docs 
Linux 2.6.38-15-generic (hersheezy)  08/14/2012 _x86_64_ (4 CPU) 

01:05:29 PM  PID minflt/s majflt/s  VSZ RSS %MEM Command 
01:05:29 PM  5360  40.23  0.00 499984 460480 5.77 python 
+++++++++++++++++++++++++++++++ 
Partition of a set of 19599 objects. Total size = 1582016 bytes. 
Index Count %  Size % Cumulative % Kind (class/dict of class) 
    0 19599 100 1582016 100 1582016 100 str 
=============================== 

Come posso essere sicuro che questo la memoria viene restituita al sistema operativo?

+1

possibile duplicato di [Perché la memoria non viene rilasciata nel sistema dopo query di grandi dimensioni (o serie di query) in django?] (Http://stackoverflow.com/questions/5494178/why-doesnt-memory-get- release-to-system-after-large-queries-or-series-of-quer) –

risposta

3

Ci può essere una differenza tra quando la memoria è resa disponibile per il riutilizzo all'interno del processo python e quando viene rilasciata nel sistema operativo. In particolare, l'interprete standard Python (CPython) mantiene i propri pool e le liste libere per particolari tipi di oggetti. Riutilizza la memoria in questi pool, ma non la rilascia mai sul sistema operativo una volta che è stata utilizzata.

Vedere this per ulteriori dettagli.

+1

Credo che risponda alla domanda postata. Le mie vere domande derivano dall'avere un daemon Python di lunga durata che assegna una tonnellata di memoria (circa il 60% della memoria del sistema) una volta al giorno per un brevissimo periodo di tempo. Al termine dell'esecuzione, l'utilizzo della memoria rimane elevato anche se pulisco i miei riferimenti. Qualche consiglio generale? Il link che hai postato sembrava dire che non dovrei semplicemente assegnare quella quantità di memoria in primo luogo ... – Hersheezy

+0

Qualunque possibilità potresti fare la cosa che richiede una tonnellata di memoria in un secondo copione, o qualcosa del genere? Oppure lanciare una seconda istanza del demone quando inizia l'elaborazione affamata di memoria, quindi uscire dopo l'elaborazione (consentendo alla seconda istanza di continuare a funzionare)? – kindall

+2

@Hersheezy: questa risposta suona plausibile ma è falsa. CPython * può * rilasciare memoria a volte. Vedi [il mio commento] (http://stackoverflow.com/questions/11957539/python-memory-not-being-given-back-to-kernel#comment15934886_11957625) – jfs

1

Come posso essere sicuro che questa memoria sia restituita al sistema operativo?

Generalmente no. Python alloca la memoria in 'arene', e anche quando i riferimenti vengono cancellati nell'interprete, rimarrà su quell'arena della memoria da usare in seguito. PENSO che ci sia un meccanismo nella versione più recente di Python per annullare le arene se sono completamente vuote. Ma non hai il controllo su dove posizionare i tuoi oggetti.

+2

[python potrebbe rilasciare arene vuote] (http://bugs.python.org/issue1123430) nel 2005. Anche se potrebbe [smettere di funzionare ] (http://bugs.python.org/msg134992) – jfs

Problemi correlati