Kebocoran memori terjadi di proyek Google App Engine Python. Adakah cara efisien untuk menulis operasi saya?

Saya memiliki proyek GAE yang ditulis dengan Python. Saya membuat cron untuk menjalankan operasi batch. Tapi itu mencapai batas memori pribadi lunak dari instance F1, yaitu 124MB setelah beberapa iterasi. Adakah yang bisa membantu saya menulis kode ini dengan lebih efisien, semoga dalam 124MB. len(orang) harus kurang dari 500.

def cron():
    q = Account.all().filter('role =', 1)
    people = [e for e in q]
    for p in people:
        s = Schedule.available(p)
        m = ScheduleMapper(s).as_dict()
        memcache.set('key_for_%s' % p.key(), m)

Ini adalah server dev dan saya tidak ingin mengupgrade kelas instance saya. Selain itu, saya ingin menghindari penggunaan perpustakaan pihak ketiga, seperti numpy dan pandas.

Saya menambahkan koleksi sampah di baris terakhir loop for. Tapi sepertinya itu tidak berhasil.

del s
m.clear()
import gc
gc.collect()

person steve    schedule 02.10.2017    source sumber
comment
Anda belum menyebutkan berapa banyak entitas yang Anda ambil. Saya juga akan memindahkan perulangan ke suatu fungsi dan gc di luar. Saat Anda mengatakan iterasi, maksud Anda pemanggilan cron handler atau loop luar atau dalam?   -  person Tim Hoffman    schedule 02.10.2017
comment
Terima kasih atas komentarnya! Jumlah entitas harus kurang dari 500. Sedangkan untuk iterasi, yang saya maksud adalah loop dalam.   -  person steve    schedule 02.10.2017
comment
berapa banyak di loop dalam. Tanpa melihat model Anda, saya curiga Anda menyimpan beberapa referensi di suatu tempat.   -  person Tim Hoffman    schedule 02.10.2017
comment
Saya tidak menghitung berapa tepatnya tetapi berakhir dengan beberapa. Ya, saya juga mencurigai referensinya. Tapi bagaimana cara melepaskan semua kenangan itu?   -  person steve    schedule 02.10.2017
comment
Dari apa yang saya lihat, del list atau dict.clear() tidak akan melepaskan semua kenangan.   -  person steve    schedule 02.10.2017
comment
Saya pikir kita perlu melihat beberapa detail di tersedia() dan melihat aliran yang melapisi apa yang Anda lakukan tanpa semua objek perantara. Lihatlah penggunaan map untuk menerapkan fungsi ke entitas daripada menyelesaikan seluruh daftar dan kemudian mengulanginya. Hal-hal seperti itu. Saya memiliki proses dengan kueri yang berfungsi pada ribuan entitas dan instance F1 saya bertahan selama berhari-hari dan tidak pernah gagal karena kesalahan kehabisan memori.   -  person Tim Hoffman    schedule 03.10.2017


Jawaban (1)


Untuk melihat apakah mungkin untuk memasukkannya ke dalam jejak memori, Anda ingin memodifikasi kueri Anda untuk mendapatkan satu entitas dan memeriksa apakah Anda berhasil mengeksekusi loop for untuk satu entitas tersebut. Atau cukup tambahkan break di akhir loop for :)

Jika tidak berhasil, Anda perlu meningkatkan kelas instance Anda.

Jika eksperimen berhasil maka Anda dapat menggunakan pembagian pekerjaan menggunakan Kursor Kueri menjadi beberapa tugas push queue, masing-masing hanya memproses satu entitas atau beberapa entitas saja.

Mungkin lihat Google appengine: Performa antrian tugas untuk diskusi tentang membagi pekerjaan menjadi beberapa tugas (walaupun alasan pemisahan dalam kasus tersebut adalah melebihi tenggat waktu permintaan, bukan batas memori).

Perhatikan bahwa meskipun menggunakan banyak tugas, batas memori masih mungkin tercapai (lihat App Engine Ditunda: Melacak Kebocoran Memori), namun setidaknya pekerjaan akan selesai meskipun instance tertentu dimulai ulang (tugas dicoba ulang secara default).

person Dan Cornilescu    schedule 09.10.2017