Saya memiliki skrip yang berjalan lama yang, jika dibiarkan berjalan cukup lama, akan menghabiskan semua memori pada sistem saya.
Tanpa merinci skrip, saya punya dua pertanyaan:
- Apakah ada "Praktik Terbaik" untuk diikuti, yang akan membantu mencegah kebocoran terjadi?
- Teknik apa yang ada untuk men-debug kebocoran memori di Python?
python
debugging
memory-management
memory-leaks
Fragsworth
sumber
sumber
__del__
metode yang tidak lagi dirujuk kecuali untuk siklus mereka. Siklus tidak dapat diputus, karena masalah dengan__del__
. Memperbaikinya!Jawaban:
Lihat artikel ini: Menelusuri kebocoran memori python
Juga, perhatikan bahwa modul pengumpulan sampah sebenarnya dapat memiliki flag debug yang ditetapkan. Lihatlah
set_debug
fungsinya. Selain itu, lihat kode ini oleh Gnibbler untuk menentukan jenis objek yang telah dibuat setelah panggilan.sumber
Saya mencoba sebagian besar opsi yang disebutkan sebelumnya tetapi menemukan paket kecil dan intuitif ini menjadi yang terbaik: pympler
Cukup mudah untuk melacak objek yang tidak dikumpulkan oleh sampah, periksa contoh kecil ini:
instal paket via
pip install pympler
Output menunjukkan kepada Anda semua objek yang telah ditambahkan, ditambah memori yang mereka konsumsi.
Output sampel:
Paket ini menyediakan sejumlah fitur lainnya. Periksa dokumentasi pympler , khususnya bagian Mengidentifikasi kebocoran memori .
sumber
pympler
bisa menjadi PERLAHAN . Jika Anda melakukan sesuatu semi-realtime, itu benar-benar dapat melumpuhkan kinerja aplikasi Anda.Biarkan saya merekomendasikan alat mem_top yang saya buat
Itu membantu saya untuk memecahkan masalah serupa
Itu hanya langsung menunjukkan tersangka atas kebocoran memori dalam program Python
sumber
Modul Tracemalloc diintegrasikan sebagai modul bawaan mulai dari Python 3.4, dan tampaknya, itu juga tersedia untuk versi sebelumnya dari Python sebagai perpustakaan pihak ketiga (belum mengujinya).
Modul ini dapat menampilkan file dan jalur yang tepat yang mengalokasikan sebagian besar memori. IMHO, informasi ini jauh lebih berharga daripada jumlah instance yang dialokasikan untuk setiap jenis (yang akhirnya menjadi banyak tuple 99% dari waktu, yang merupakan petunjuk, tetapi hampir tidak membantu dalam kebanyakan kasus).
Saya sarankan Anda menggunakan tracemalloc dalam kombinasi dengan pyrasite . 9 kali dari 10, menjalankan potongan 10 teratas dalam cangkang pyrasite akan memberi Anda informasi dan petunjuk yang cukup untuk memperbaiki kebocoran dalam waktu 10 menit. Namun, jika Anda masih tidak dapat menemukan penyebab kebocorannya, shell-pyrasite yang dikombinasikan dengan alat-alat lain yang disebutkan di utas ini mungkin akan memberi Anda beberapa petunjuk lagi. Anda juga harus melihat pada semua pembantu tambahan yang disediakan oleh pyrasite (seperti penampil memori).
sumber
Anda harus secara khusus melihat data global atau statis Anda (data yang berumur panjang).
Ketika data ini tumbuh tanpa batasan, Anda juga bisa mendapatkan masalah dengan Python.
Pengumpul sampah hanya dapat mengumpulkan data, yang tidak dirujuk lagi. Tetapi data statis Anda dapat menghubungkan elemen data yang harus dibebaskan.
Masalah lain dapat berupa siklus memori, tetapi setidaknya secara teori pengumpul sampah harus menemukan dan menghilangkan siklus - setidaknya selama mereka tidak terikat pada beberapa data yang hidup lama.
Jenis data umur panjang apa yang secara khusus menyusahkan? Lihatlah daftar dan kamus - mereka dapat tumbuh tanpa batas. Dalam kamus Anda bahkan mungkin tidak melihat masalah yang datang karena ketika Anda mengakses dicts, jumlah kunci dalam kamus mungkin tidak memiliki visibilitas besar kepada Anda ...
sumber
Untuk mendeteksi dan menemukan kebocoran memori untuk proses yang berjalan lama, misalnya di lingkungan produksi, Anda sekarang dapat menggunakan stackimpact . Ini menggunakan tracemalloc di bawahnya. Info lebih lanjut di posting ini .
sumber
Sejauh praktik terbaik, perhatikan fungsi rekursif. Dalam kasus saya, saya mengalami masalah dengan rekursi (di mana tidak perlu). Contoh sederhana dari apa yang saya lakukan:
beroperasi dengan cara rekursif ini tidak akan memicu pengumpulan sampah dan membersihkan sisa-sisa fungsi, sehingga setiap kali melalui penggunaan memori tumbuh dan tumbuh.
Solusi saya adalah dengan menarik panggilan rekursif dari my_function () dan memiliki main () menangani kapan harus memanggilnya lagi. dengan cara ini fungsi berakhir secara alami dan membersihkan sendiri.
sumber
Tidak yakin tentang "Praktik Terbaik" untuk kebocoran memori di python, tetapi python harus menghapus memori sendiri oleh pengumpul sampah itu. Jadi terutama saya akan mulai dengan memeriksa daftar bundar beberapa pendek, karena mereka tidak akan diambil oleh pengumpul sampah.
sumber
Ini tidak berarti saran lengkap. Tetapi hal pertama yang perlu diingat ketika menulis dengan pemikiran untuk menghindari kebocoran memori masa depan adalah untuk memastikan bahwa apa pun yang menerima referensi untuk panggilan balik, harus menyimpan panggilan kembali itu sebagai referensi yang lemah.
sumber