2011-03-17 29 views
6

Sto osservando uno strano pattern di utilizzo della memoria con stringhe python su Freebsd. Considerare la seguente sessione. L'idea è di creare un elenco che contenga alcune stringhe in modo che i caratteri cumulativi nell'elenco siano 100 MB.Utilizzo della memoria String Python su FreeBSD

l = [] 
for i in xrange(100000): 
    l.append(str(i) * (1000/len(str(i)))) 

Questo utilizza circa 100 MB di memoria come previsto e "del l" lo cancellerà.

l = [] 
for i in xrange(20000): 
    l.append(str(i) * (5000/len(str(i)))) 

Questo sta utilizzando 165 MB di memoria. Non capisco davvero da dove provenga l'utilizzo della memoria aggiuntiva . [Formato di entrambe le liste sono gli stessi]

Python 2.6.4 su FreeBSD 7.2. Su Linux/Windows utilizza entrambi attorno alla memoria solo da .

Update: Sto misura memoria usando 'ps aux'. Questo può essere eseguito usando os.sytem dopo i frammenti di codice sopra. Anche questi sono stati eseguiti separatamente.

Update2: Sembra memoria di mallocs freebsd in multipli di 2. Quindi allocare 5 KB in realtà alloca 8 KB. Non sono sicuro però.

+0

Che dire prima esecuzione della seconda parte del codice quindi eseguire il primo? Penso di nuovo che ci saranno 165 MB perché questo riguarda il modo in cui il sistema operativo/interprete python e garbage collector gestiscono la memoria. – Hossein

+5

Come si determina la memoria che utilizza? Sei sicuro che sia corretto? – steabert

risposta

0

La risposta potrebbe essere in this saga. Penso che tu stia assistendo ad un inevitabile sovraccarico del memory manager.

Come dice @Hossein, prova ad eseguire entrambi i frammenti di codice in un'unica esecuzione, quindi li scambia.

1

, a mio avviso, che probabilmente sarebbe frammenti di memoria. Prima di tutto, i blocchi di memoria che sono maggiori di 255 byte saranno allocati con malloc in CPython. È possibile fare riferimento a

Improving Python's Memory Allocator

Per motivi di prestazioni, la maggior parte di allocazione di memoria, come malloc, restituirà un indirizzo allineato. Ad esempio, si potrà mai ottenere un indirizzo del tipo

0x00003 

Non è allineato da 4 byte, sarebbe molto lento per computer di accedere alla memoria. Pertanto, tutti gli indirizzi ricevuti da malloc devono essere

0x00000 
0x00004 
0x00008 

e così via. L'allineamento di 4 byte è solo la regola comune di base, la vera politica di allineamento sarebbe la variante del sistema operativo.

E l'utilizzo della memoria si sta parlando dovrebbe essere RSS (non sono sicuro). Per gran parte del sistema operativo, la dimensione della pagina della memoria virtuale è 4K. Per ciò che si assegna, è necessario 2 pagine per la memorizzazione di un chunk di 5000 byte. Vediamo un esempio per illustrare qualche perdita di memoria. Supponiamo che l'allineamento sia di 256 byte qui.

0x00000 { 
...  chunk 1 
0x01388 } 
0x01389 { 
...  fragment 1 
0x013FF } 
0x01400 { 
...  chunk 2 
0x02788 } 
0x02789 { 
...  fragment 2 
0x027FF } 
0x02800 { 
...  chunk 3 
0x03B88 } 
0x03B89 { 
...  fragment 3 
0x04000 } 

Come potete vedere ci sono così tanti frammenti nella memoria, che non può essere utilizzato, ma ancora, che occupano lo spazio di memoria di una pagina. Non sono sicuro di quale sia la politica di allineamento di FreeBSD, ma penso che sia causata da una ragione come questa. Per utilizzare la memoria in modo efficiente con Python, è possibile utilizzare una grande porzione di bytearray preassegnati e scegliere un buon numero come il blocco da utilizzare (è necessario testare per sapere quale numero è il migliore, dipende dal sistema operativo).

0

Penso che tutti gli indirizzi di memoria in FreeBSD devono essere allineati alla potenza di due.Quindi tutti i pool di memoria di Python sono in qualche modo frammentati nella memoria e non continui.

tenta di utilizzare qualche altro tool da individuare qualcosa di interessante