2010-06-21 1 views
5

Program, który napisałem, przechowuje dużą ilość danych w słownikach. W szczególności tworzę 1588 wystąpień klasy, z których każda zawiera 15 słowników z 1500 odwzorowaniami float. Ten proces dość szybko zużył 2 GB pamięci na moim laptopie (zaczynam pisać, aby zamienić się na około 1000. instancji klasy).Użycie pamięci Python: Który z moich obiektów zużywa najwięcej pamięci?

Moje pytanie brzmi, które z poniższych czynności powoduje wyczerpanie pamięci?

  • 34 miliony niektóre pary pływaków?
  • Koszt ponad 22 500 słowników?
  • koszt 1500 zajęć?

Dla mnie wygląda na to, że świnia pamięciowa to ogromna liczba liczb zmiennoprzecinkowych, które trzymam w pamięci. Jeśli jednak to, co przeczytałem do tej pory, jest poprawne, każda z liczb zmiennoprzecinkowych zajmuje 16 bajtów. Ponieważ mam 34 miliony par, powinno to wynosić około 108 milionów bajtów, co powinno wynosić nieco ponad gigabajt.

Czy jest coś, czego nie biorę tutaj pod uwagę?

Odpowiedz

7

Pływaki zrobić zajmują 16 bajtów za sztukę, a DICT 1500 wpisów około 100k:

>> sys.getsizeof(1.0) 
16 
>>> d = dict.fromkeys((float(i) for i in range(1500)), 2.0) 
>>> sys.getsizeof(d) 
98444 

więc 22.500 dicts przejmują 2GB wszystkim siebie, po 68 mln unosi kolejny GB lub więcej. Nie wiem, jak obliczyć 68 milionów razy 16 równe tylko 100 M - być może gdzieś zrzuciłeś zero.

Sama klasa zajmuje niewielką ilość, a 1500 jej wystąpień (bez obiektów, do których się odnoszą, tak jak getsizeof daje nam takie kwoty netto za dyktanda) niewiele więcej niż niewielki dyktat każdy, więc , to nie jest problem. Tj .:

>>> sys.getsizeof(Sic) 
452 
>>> sys.getsizeof(Sic()) 
32 
>>> sys.getsizeof(Sic().__dict__) 
524 

452 dla klasy, (524 + 32) * 1550 = 862K dla wszystkich przypadkach, jak widać nie jest to zmartwienie, gdy masz gigabajtów każdy w dicts i pływaków.

+0

Jeśli podłączę zakres (1000) lub zakres (1250) zamiast 1500 w powyższym kodzie, otrzymam rozmiar 24712 bajtów. Wydaje się, że to prawda, aż do zakresu (1365), w którym to momencie następuje dyskretny skok w rozmiarze. Czy to prawda, w jaki sposób Python przydziela pamięć? Jeśli tak, dlaczego tak się dzieje? – Wilduck

+0

I chociaż float w języku Python został zaimplementowany przy użyciu podwójnego C, który ogólnie byłby 64-bitowy (8 bajtów). A podwójny typ zajmuje 8 bajtów w module 'struct'. Nie mogę się spierać z wynikiem 'getsizeof' chociaż ... –

+1

@Scott, każdy obiekt Pythona ma pewne obciążenie (licznik odwołania, wskaźnik do typu) oprócz jego" ładunku ", a wszystkie alokacje są zaokrąglane w górę do wielokrotności 16 bajtów, aby grać ładnie wraz z systemowym malloc. Aby zachować kompaktowość, możesz użyć ich "array.array" (ale to lista nie przypominająca dyktowania). –