Python bellek sızıntıları [kapalı]


180

Yeterince uzun süre çalışmasına izin verirseniz, sistemimdeki tüm belleği tüketecek uzun çalışan bir komut dosyası var.

Senaryo hakkında ayrıntılara girmeden iki sorum var:

  1. Sızıntıların oluşmasını önlemeye yardımcı olacak bir "En İyi Uygulamalar" var mı?
  2. Python'da bellek sızıntılarını gidermek için hangi teknikler var?

5
Bu tarifi yararlı buldum .
David Schein

Yararlı olmak için çok fazla veri yazdırıyor gibi görünüyor
Casebash

1
@Casebash: Bu işlev ciddi bir şey yazdırıyorsa, ciddi şekilde yanlış yapıyorsunuz demektir. __del__Döngüsü dışında artık başvurulmayan yöntemi olan nesneleri listeler . Döngü, ile ilgili sorunlar nedeniyle kırılamaz __del__. Düzelt!
Helmut Grohne

Yanıtlar:



83

Daha önce bahsedilen çoğu seçeneği denedim ama bu küçük ve sezgisel paketi en iyi buldum : pympler

Çöp toplamayan nesneleri izlemek oldukça basittir, bu küçük örneği kontrol edin:

paketi üzerinden yükle pip install pympler

from pympler.tracker import SummaryTracker
tracker = SummaryTracker()

# ... some code you want to investigate ...

tracker.print_diff()

Çıktı, eklenen tüm nesneleri ve bunların harcadığı belleği gösterir.

Örnek çıktı:

                                 types |   # objects |   total size
====================================== | =========== | ============
                                  list |        1095 |    160.78 KB
                                   str |        1093 |     66.33 KB
                                   int |         120 |      2.81 KB
                                  dict |           3 |       840 B
      frame (codename: create_summary) |           1 |       560 B
          frame (codename: print_diff) |           1 |       480 B

Bu paket birkaç özellik daha sağlar. Kontrol pympler belgelerine , özellikle bölüm bellek sızıntıları tanımlama .


5
YAVAŞpympler olabileceğini belirtmek gerekir . Yarı gerçek zamanlı bir şey yapıyorsanız, uygulama performansınızı tamamen azaltabilir.
Sahte İsim

@sebpiq garip bir şekilde, benim için de aynı şey oluyor ... bunun neden olduğu hakkında bir fikrin var mı? Kaynak koduna hızlıca bakmak gerçek bir fikir vermedi.
linusg

25

Bana tavsiye edelim mem_top oluşturulan alet I

Benzer bir sorunu çözmeme yardımcı oldu

Bir Python programındaki bellek sızıntıları için en iyi şüphelileri anında gösterir


1
bu doğru ... ama kullanım / sonuçların açıklanmasında çok az şey veriyor
me_

@ me_, bu araç belgelenmiş hem "Kullanım" hem de "Sonuç açıklanıyor" bölümlerine sahiptir. "Refs, nesneden yapılan başvuruların sayısı, bu türdeki nesnelerin sayısı, baytların nesnenin boyutu" gibi bir açıklama eklemeliyim - bunu belgelemek çok açık olmaz mıydı?
Denis Ryzhkov

aracın kullanım dokümanları "zaman zaman: logging.debug (mem_top ())" diyen tek bir satır verirken, sonuçların açıklaması yazarın bağlamsız gerçek hayat hatası izleme deneyimidir ... bu teknik bir özellik değildir. tam olarak neye baktıklarını söylüyorum ... Cevabınızı çalmıyorum ... faturalanmış olarak üst düzey şüphelileri gösteriyor ... kullanım sonucunu tam olarak anlamak için yeterli belge vermiyor ... örneğin , "Sonuçları Açıklama" çıkışında "GearmanJobRequest" neden bir sorun var? neden için hiçbir açıklama yok ...
me_

1
sanırım yanlışlıkla aracınızı
çalıyorum

6
@ me_, "Kullanım" a bir sonraki adımı ekledim, "Sayaçlar" bölümünü ekledim, Gearman'ın neden gerçek hayattaki bir örnekte tam olarak şüpheli olduğunu belirttim, koddaki her "isteğe bağlı" mem_top () "parametresini belgeledim, ve bunların hepsini v0.1.7 olarak yüklediniz. Lütfen başka bir şeyin iyileştirilebileceğini kontrol edin. Teşekkür ederim! )
Denis Ryzhkov

18

Tracemalloc modülü , Python 3.4'ten başlayarak yerleşik bir modül olarak entegre edildi ve görünüşe göre, Python'un önceki parti sürümleri için üçüncü taraf kitaplığı olarak da mevcut (yine de test etmedi).

Bu modül, en fazla belleği ayıran kesin dosyaları ve çizgileri çıktılayabilir. IMHO, bu bilgi her tür için tahsis edilen örnek sayısından sonsuz olarak daha değerlidir (bu, bir ipucu olan, ancak çoğu durumda zar zor yardımcı olan, zamanın% 99'unda çok fazla tuple olur).

Ben birlikte tracemalloc kullanmanızı tavsiye pyrasite . 10'dan 9 kez, en iyi 10 snippet'i bir piramit kabuğunda çalıştırmak , sızıntıyı 10 dakika içinde düzeltmek için yeterli bilgi ve ipuçları verecektir. Yine de, sızıntı nedenini hala bulamıyorsanız, bu iş parçacığında bahsedilen diğer araçlarla birlikte pyrasite kabuğu muhtemelen size daha fazla ipucu verecektir. Ayrıca, prasit (bellek görüntüleyici gibi) tarafından sağlanan tüm ekstra yardımcılara da göz atmalısınız.



12

Küresel veya statik verilerinize özellikle bakmalısınız (uzun ömürlü veriler).

Bu veriler kısıtlama olmadan büyüdüğünde, Python'da da sorun yaşayabilirsiniz.

Çöp toplayıcı yalnızca artık referans alınmayan verileri toplayabilir. Ancak statik verileriniz, serbest bırakılması gereken veri öğelerini birleştirebilir.

Başka bir sorun bellek döngüleri olabilir, ancak en azından teoride Çöp toplayıcı döngüleri bulmalı ve ortadan kaldırmalıdır - en azından bazı uzun yaşayan verilere bağlı olmadıkları sürece.

Ne tür uzun ömürlü veriler özellikle zahmetlidir? Herhangi bir liste ve sözlüklere iyi bakın - sınırsız büyüyebilirler. Sözlüklerde, diktelere eriştiğinizde, sözlükteki anahtarların sayısı sizin için çok fazla görünmeyebileceğinden, gelen sorunu göremeyebilirsiniz bile ...



4

En iyi uygulamalara gelince, özyinelemeli işlevlere dikkat edin. Benim durumumda (burada olması gerekmedi) özyineleme ile ilgili sorunlar koştu. Ne yaptığımın basitleştirilmiş bir örneği:

def my_function():
    # lots of memory intensive operations
    # like operating on images or huge dictionaries and lists
    .....
    my_flag = True
    if my_flag:  # restart the function if a certain flag is true
        my_function()

def main():
    my_function()

bu özyinelemeli şekilde çalışmak çöp toplamayı tetiklemez ve işlevin kalıntılarını temizlemez, bu nedenle bellek kullanımıyla her seferinde büyür ve büyür.

Benim çözümüm özyinelemeli çağrımı my_function () 'den çıkarmak ve tekrar çağırmak için main () tutamacına sahip olmaktı. bu şekilde işlev doğal olarak sona erer ve kendinden sonra temizlenir.

def my_function():
    # lots of memory intensive operations
    # like operating on images or huge dictionaries and lists
    .....
    my_flag = True
    .....
    return my_flag

def main():
    result = my_function()
    if result:
        my_function()

7
Özyineleme derinliği sınırına ulaşırsanız özyineleme bu şekilde kullanılırsa, Python kuyruk çağrılarını optimize etmez. Varsayılan olarak, bu 1000 özyinelemeli çağrıdır.
Yalan Ryan

3

Python'da bellek sızıntıları için "En İyi Uygulamalar" konusunda emin değilim, ancak python çöp toplayıcısı tarafından kendi belleğini temizlemelidir. Bu yüzden esasen çöp toplayıcı tarafından alınamayacağı için kısa listelerin dairesel listesini kontrol ederek başlayacağım.


3
veya sonsuza kadar saklanan nesnelere referanslar vb.
mat b

3
Sonsuza kadar saklanan dairesel listelere ve nesnelere örnekler verebilir misiniz?
Daniel

2

Bu kesinlikle kapsamlı bir tavsiye değildir. Ancak, gelecekteki bellek sızıntılarından (döngüler) kaçınma düşüncesi ile yazarken akılda tutulması gereken bir numaralı şey, bir geri aramaya referans kabul eden herhangi bir şeyin bu geri aramayı zayıf bir referans olarak saklaması gerektiğinden emin olmaktır.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.