Pri pokusoch o jemné vyladenie niektorých netesností pamäte v väzbách Pythonu pre niektoré funkcie C / C ++ narazím na nejaké podivné správanie týkajúce sa zbierky odpadkov Numpy polí.
Vytvoril som niekoľko zjednodušených prípadov, aby som lepšie vysvetlil svoje správanie. Kód bol spustený pomocou memory_profiler
, výstup, z ktorého vyplýva bezprostredne potom. Zdá sa, že zbierka odpadkov Pythonu nefunguje podľa očakávaní, pokiaľ ide o polia NumPy:
# File deallocate_ndarray.py
@profile
def ndarray_deletion():
import numpy as np
from gc import collect
buf = "abcdefghijklmnopqrstuvwxyz" * 10000
arr = np.frombuffer(buf)
del arr
del buf
collect()
y = [i**2 for i in xrange(10000)]
del y
collect()
if __name__=="__main__":
ndarray_deletion()
Nasledujúcim príkazom som vyvolala memory_profiler
:
python -m memory_profiler deallocate_ndarray.py
To je to, čo som dostal:
Filename: deallocate_ndarray.py
Line # Mem usage Increment Line Contents
================================================
5 10.379 MiB 0.000 MiB @profile
6 def ndarray_deletion():
7 17.746 MiB 7.367 MiB import numpy as np
8 17.746 MiB 0.000 MiB from gc import collect
9 17.996 MiB 0.250 MiB buf = "abcdefghijklmnopqrstuvwxyz" * 10000
10 18.004 MiB 0.008 MiB arr = np.frombuffer(buf)
11 18.004 MiB 0.000 MiB del arr
12 18.004 MiB 0.000 MiB del buf
13 18.004 MiB 0.000 MiB collect()
14 18.359 MiB 0.355 MiB y = [i**2 for i in xrange(10000)]
15 18.359 MiB 0.000 MiB del y
16 18.359 MiB 0.000 MiB collect()
Nerozumiem, prečo aj nútené volania collect
neznížite využitie pamäte programomuvoľnenie nejakej pamäte. Navyše, aj keď sa Numpy polia nechovajú normálne kvôli základným C konštruktom, prečo sa tento zoznam (čo je čistý Python) nezhromažďuje?
viem že del
priamo nenazýva podkladové __del__
metóda, ale všimnete si to všetko del
tvrdenia v kóde skutočne skončia znižovanímreferenčný počet zodpovedajúcich predmetov na nulu (čím sa stáva oprávneným na zber odpadkov AFAIK). Obvykle by som očakával negatívny záznam v stĺpci prírastkov, keď sa objekt podrobí zberu odpadu. Môže niekto objasniť, čo sa tu deje?
POZNÁMKA: Tento test sa uskutočnil na OS X 10.10.4, Python 2.7.10 (conda), Numpy 1.9.2 (conda), Memory Profiler 0.33 (conda-binstar), psutil 2.2.1 (conda).
odpovede:
3 pre odpoveď č. 1Aby som videl zhromaždené odpadky z pamäte, musel som zväčšiť veľkosť bufu o niekoľko rádov. Možno je veľkosť príliš malá memory_profiler
na detekciu zmeny (pýta sa na OS, takže merania nie sú príliš presné) alebo možno je príliš malá na to, aby sa mohla zberateľ odpadu Python postarať, neviem.
Napríklad nahradenie faktora 10000 číslom 100000000 buf
výťažky
Line # Mem usage Increment Line Contents
================================================
21 10.289 MiB 0.000 MiB @profile
22 def ndarray_deletion():
23 17.309 MiB 7.020 MiB import numpy as np
24 17.309 MiB 0.000 MiB from gc import collect
25 2496.863 MiB 2479.555 MiB buf = "abcdefghijklmnopqrstuvwxyz" * 100000000
26 2496.867 MiB 0.004 MiB arr = np.frombuffer(buf)
27 2496.867 MiB 0.000 MiB del arr
28 17.312 MiB -2479.555 MiB del buf
29 17.312 MiB 0.000 MiB collect()
30 17.719 MiB 0.406 MiB y = [i**2 for i in xrange(10000)]
31 17.719 MiB 0.000 MiB del y
32 17.719 MiB 0.000 MiB collect()