2011-06-30 17 views
5
import json 
import time 
from itertools import count 

def keygen(size): 
    for i in count(1): 
     s = str(i) 
     yield '0' * (size - len(s)) + str(s) 

def jsontest(num): 
    keys = keygen(20) 
    kvjson = json.dumps(dict((keys.next(), '0' * 200) for i in range(num))) 
    kvpairs = json.loads(kvjson) 
    del kvpairs # Not required. Just to check if it makes any difference        
    print 'load completed' 

jsontest(500000) 

while 1: 
    time.sleep(1) 

Linux top wskazuje, że proces Python posiada ~ 450MB RAM po zakończeniu 'jsontest' funkcji. Jeśli połączenie z "json.loads" zostanie pominięte, problem nie zostanie zauważony. A gc.collect po wykonaniu tej funkcji zwalnia pamięć.Python json pamięć uwędzić

Wygląda na to, że pamięć nie jest przechowywana w żadnych pamięciach podręcznych lub wewnętrznym alokatorze pamięci Pythona, ponieważ jawne wywołanie gc.collect zwalnia pamięć.

Czy tak się dzieje, ponieważ próg do zbierania śmieci (700, 10, 10) nigdy nie został osiągnięty?

Wprowadziłem kod po jsontest, aby symulować próg. Ale to nie pomogło.

Odpowiedz

2

umieścić to na górze programu

import gc 
gc.set_debug(gc.DEBUG_STATS) 

a dostaniesz wydruk gdy istnieje zbiór. Zobaczysz, że w twoim przykładowym kodzie nie ma kolekcji po zakończeniu jsontest, dopóki program nie zostanie zamknięty.

Można umieścić

print gc.get_count() 

aby zobaczyć aktualne liczy. Pierwsza liczba to nadmiar alokacji nad dealokacjami od ostatniego zbioru generacji 0; drugi (lub trzeci) to liczba razy, gdy generacja 0 (odpowiednio 1) została zebrana od ostatniego zbioru generacji 1 (odpowiednio 2). Jeśli wydrukujesz je zaraz po zakończeniu jsontest, zobaczysz, że liczba ta wynosi (548, 6, 0) lub coś podobnego (bez wątpienia różni się to w zależności od wersji Pythona). Próg nie został osiągnięty i nie nastąpiło gromadzenie danych.

Jest to typowe zachowanie dla harmonogramu zbierania śmieci opartego na wartościach progowych. Jeśli potrzebujesz wolnej pamięci, która ma być zwrócona do systemu operacyjnego w odpowiednim czasie, musisz połączyć harmonogramowanie oparte na progach z harmonogramem opartym na czasie (czyli zażądać kolejnej kolekcji po upływie określonego czasu od ostatniej kolekcji , nawet jeśli próg nie został osiągnięty).

+0

Nawet jeśli wielokrotnie wywoływamy jsontest, pamięć pozostaje na ~ 450MB. Czy to jest pamięć używana przez ostatnie wywołanie jsontest? Ten kod jest częścią webapp, który przetwarza wiadomości json. Nawet po uruchomieniu aplikacji internetowej przez godzinę pamięć nie wydaje się być zwolniona. Czy istnieje obejście tego innego rozwiązania niż gc.collect? – Anoop

+1

Spróbuj wydrukować 'gc.get_count()' po każdym wywołaniu 'jsontest', a wszystkie powinny być jasne. Co jest złego w wywołaniu 'gc.collect'? –