Benim python uygulamalarından biri, bellek kullanımını giderek artan bellek kullanımından kaynaklanıyor gibi görünüyor. Benim hipotezim, bunun önüne geçmek için en iyi çabalara rağmen, bir yerlerde döngüsel bir referanstır. Sorunu yalıtmak için, yalnızca hata ayıklama amaçlı bir araç olan erişilemeyen öğeleri manuel olarak kontrol etmenin yollarını araştırıyorum.python'un gc.garbage öğesinin (bellek sızıntılarının izlenmesi için) anlaşılmasıyla ilgili sorun
gc modülü gerekli izleme yeteneğine sahip görünüyor ve son çağrıdan bu yana oluşturulmuş, okunamayan öğelerin bir listesini derlemeyi amaçlayan aşağıdaki kodu denedim. İlk çağrı sadece bir baz kontrol noktasını ayarlar ve ulaşılamaz öğeleri tanımlamaz.
def unreachable():
# first time setup
import gc
gc.set_threshold(0) # only manual sweeps
gc.set_debug(gc.DEBUG_SAVEALL) # keep unreachable items as garbage
gc.enable() # start gc if not yet running (is this necessary?)
# operation
if gc.collect() == 0:
return 'no unreachable items'
s = 'unreachable items:\n ' \
+ '\n '.join('[%d] %s' % item for item in enumerate(gc.garbage))
_deep_purge_list(gc.garbage) # remove unreachable items
return s # return unreachable items as text
Burada, _deep_purge_list döngüleri kesmeyi ve nesneleri el ile kaldırmayı amaçlamaktadır. Aşağıdaki uygulama bazı yaygın durumları ele alır, ancak su geçirmez değildir. İlk sorum, bununla ilgilidir, aşağıya bakın. Çok sınırlı testlere dayanarak kurulumun düzgün şekilde çalıştığı görülüyor. Aşağıdaki döngüsel başvuru doğru bir kez raporlar:
class A(object):
def __init__(self):
self.ref = self
print unreachable()
# no unreachable items
A()
print unreachable()
# unreachable items:
# [0] <__main__.A object at 0xb74579ac>
# [1] {'ref': <__main__.A object at 0xb74579ac>}
print unreachable()
# no unreachable items
Ancak garip aşağıdaki şey olur şununla:
print unreachable()
# no unreachable items
import numpy
print unreachable()
# unreachable items:
# [0] (<type '_ctypes.Array'>,)
# [1] {'__module__': 'numpy.ctypeslib', '__dict__': <attribute '__dict__' of 'c_long_Array_1' objects>, '__weakref__': <attribute '__weakref__' of 'c_long_Array_1' objects>, '_length_': 1, '_type_': <class 'ctypes.c_long'>, '__doc__': None}
# [2] <class 'numpy.ctypeslib.c_long_Array_1'>
# [3] <attribute '__dict__' of 'c_long_Array_1' objects>
# [4] <attribute '__weakref__' of 'c_long_Array_1' objects>
# [5] (<class 'numpy.ctypeslib.c_long_Array_1'>, <type '_ctypes.Array'>, <type '_ctypes._CData'>, <type 'object'>)
print unreachable()
# unreachable items:
# [0] (<type '_ctypes.Array'>,)
# [1] {}
# [2] <class 'c_long_Array_1'>
# [3] (<class 'c_long_Array_1'>, <type '_ctypes.Array'>, <type '_ctypes._CData'>, <type 'object'>)
Tekrarlanan invokasyonlar geçen sonucunu dönmeye devam. İçe aktarma işleminden sonra ilk kez erişilemediğinde sorun oluşmaz. Ancak, bu noktada, bu sorunun özgül olduğuna inanıyorum; Benim tahminim yaklaşımımda bir kusur ortaya çıkarır.
Sorularım:
- gc.garbage öğeleri kaldırmak için daha iyi bir yolu var mı? İdeal olarak, gc'yi kaldırmanın bir yolu var mıdır, DEBUG_SAVEALL olmadan yapmış mıdır?
- Sorunu numpy içe aktarma ile açıklayan herhangi biri olabilir mi ve/veya bunu düzeltmenin yollarını önerebilir mi?
Afterthought:
Bu kod aşağıda amaçlanan yakın performansa sahip olduğunu görüntülenir: gc tarafından sağlanan
def unreachable():
import gc
gc.set_threshold(0)
gc.set_debug(gc.DEBUG_LEAK)
gc.enable()
print 'collecting {{{'
gc.collect()
print '}}} done'
Ancak, hata ayıklama için ben tipi/id üzerinde zengin dize temsilleri tercih ederim. Ayrıca, eski yaklaşımımdaki kusuru anlamak ve gc modülü hakkında bir şeyler öğrenmek istiyorum.
yardımına takdir ederek,
Gertjan
Güncelleme 05/06:
yerli() hemen önce denirdi sürece, ilk uygulama herhangi ulaşılamaz öğeleri rapor vermedi bir durum ile karşılaştım ona (dönüş değerini atma). Bunun, gc'nin nesne izlemesini nasıl etkileyeceğini anlamıyorum, bu beni daha da şaşırtıyor. Bu sorunu gösteren küçük bir örnek oluşturmanın ne kadar kolay olacağından emin değilim, ancak talep çağıracağından bir çekim yapabilirim.
Sadece bunu gözden geçirdim, ancak "gc.DEBUG_SAVEALL" ifadesini yanlış anlamış olabilirsiniz: serbest bırakılan nesneleri "gc.garbage" öğesine eklemek yeterlidir (yalnızca onları serbest bırakmak yerine). – blueyed