eryksun 1. soruyu cevapladı ve ben 3. soruyu (orijinal 4. soru) cevapladım, ama şimdi 2. soruyu cevaplayalım:
Neden özellikle 50.5mb yayınlıyor - serbest bırakılan miktar neye dayanıyor?
Nihayetinde dayandığı şey, Python içindeki ve malloc
tahmin edilmesi çok zor olan bir dizi tesadüf .
Birincisi, belleği nasıl ölçtüğünüze bağlı olarak, yalnızca gerçekten belleğe eşlenmiş sayfaları ölçüyor olabilirsiniz. Bu durumda, bir sayfa çağrı cihazı tarafından her değiştirildiğinde, bellek serbest bırakılmamış olsa bile "serbest" olarak görünecektir.
Veya tahsis edilmiş ama hiç dokunulmamış sayfaları (linux gibi iyimser bir şekilde fazla tahsis eden sistemlerde), tahsis edilmiş ancak etiketlenmiş sayfaları MADV_FREE
vb. Sayan veya saymayan kullanımdaki sayfaları ölçüyor olabilirsiniz .
Tahsis edilmiş sayfaları gerçekten ölçüyorsanız (ki bu aslında yapmak için çok yararlı bir şey değil, ama sorduğunuz şey gibi görünüyor) ve sayfaların tahsisi gerçekten kaldırılmışsa, bunun olabileceği iki koşul: Ya siz ' brk
veri segmentini küçültmek için kullandınız veya eşdeğeri (günümüzde çok nadirdir) veya munmap
eşlenmiş bir segmenti serbest bırakmak için kullandınız veya benzer. (Ayrıca teorik olarak ikincisinin küçük bir varyantı vardır, çünkü eşlenmiş bir segmentin bir kısmını serbest bırakmanın yolları vardır - örneğin, eşlemesini hemen kaldırdığınız MAP_FIXED
bir MADV_FREE
segment için onu çalın.)
Ancak çoğu program bir şeyleri doğrudan bellek sayfalarından ayırmaz; Onlar kullanmak malloc
tarzı ayırıcı. Aradığınızda free
, ayırıcı, yalnızca free
bir eşlemede (veya veri segmentinin son N sayfasında) son canlı nesne olursanız, sayfaları işletim sistemine bırakabilir . Uygulamanızın bunu mantıklı bir şekilde tahmin etmesi veya önceden olduğunu tespit etmesi mümkün değildir.
CPython bunu daha da karmaşık hale getirir - üzerinde özel bir bellek ayırıcının üzerinde özel 2 seviyeli bir nesne ayırıcıya sahiptir malloc
. ( Daha ayrıntılı bir açıklama için kaynak yorumlarına bakın .) Üstelik C API düzeyinde bile Python çok daha az, en üst düzey nesnelerin ayrıldıklarında doğrudan kontrol bile edemezsiniz.
Öyleyse, bir nesneyi serbest bıraktığınızda, işletim sisteminin belleği serbest bırakıp bırakmayacağını nasıl anlarsınız? Öncelikle, son referansı (bilmediğiniz dahili referanslar dahil) yayınladığınızı ve GC'nin onu serbest bırakmasına izin verdiğinizi bilmelisiniz. (Diğer uygulamalardan farklı olarak, en azından CPython bir nesneyi izin verildiği anda serbest bırakacaktır.) Bu genellikle bir sonraki seviyedeki en az iki şeyi serbest bırakır (örneğin, bir dizge için, PyString
nesneyi ve dize arabelleğini serbest bırakıyorsunuz) ).
Eğer varsa yapmak bu nesne depolama bloğunu ayırması sonraki seviye aşağı neden olmadığını bilmek, bir nesneyi ayırması, sen nasıl uygulandığı gibi, nesne ayırıcı iç durumunu bilmek zorunda. (Bloktaki son şeyi serbest bırakmadığınız sürece bu kesinlikle gerçekleşmez ve o zaman bile gerçekleşmeyebilir.)
Eğer varsa yapmak bu bir neden olmadığını bilmek, nesne depolama bloğunu ayırması free
çağrı, sen nasıl uygulandığı yanı sıra PyMem ayırıcı iç durumunu bilmek zorunda. (Yine, bir malloc
ed bölgede son kullanımdaki bloğu kaldırmanız gerekir ve o zaman bile gerçekleşmeyebilir.)
Eğer varsa yapmak free
bir malloc
ed bölgesini, bu bir sebep olmadığını bilmek munmap
veya eşdeğeri (veya brk
, sen iç durumu bilmek zorunda) malloc
nasıl uygulandığı yanı sıra. Ve bu, diğerlerinin aksine, oldukça platforma özgüdür. (Ve yine, genellikle malloc
bir mmap
segmentte son kullanımda olanı kaldırmanız gerekir ve o zaman bile gerçekleşmeyebilir.)
Bu yüzden, neden tam olarak 50.5 MB'yi serbest bıraktığını anlamak istiyorsanız, onu aşağıdan yukarıya doğru izlemeniz gerekecek. malloc
Bu bir veya daha fazla free
aramayı yaptığınızda neden 50.5 MB değerinde sayfanın haritasını çıkardınız (muhtemelen 50.5 MB'den biraz fazla)? Platformunuzu okumanız malloc
ve ardından mevcut durumunu görmek için çeşitli tabloları ve listeleri incelemeniz gerekir. (Bazı platformlarda, çevrimdışıyken incelemek için sistemin anlık görüntüsünü almadan yakalanması neredeyse imkansız olan sistem düzeyinde bilgileri bile kullanabilir, ancak neyse ki bu genellikle bir sorun değildir.) Ve sonra yapmanız gerekir. bunun üzerindeki 3 seviyede de aynı şeyi yapın.
Bu nedenle, sorunun tek yararlı cevabı "Çünkü" dir.
Kaynakla sınırlı (ör. Yerleşik) geliştirme yapmadığınız sürece, bu ayrıntılarla ilgilenmek için hiçbir nedeniniz yoktur.
Eğer olursa edilir kaynakları sınırlı geliştirme yaparak, bu ayrıntıları bilmeden işe yaramaz; hemen hemen tüm bu seviyelerde ve özellikle mmap
uygulama seviyesinde ihtiyaç duyduğunuz belleği (muhtemelen arada basit, iyi anlaşılmış, uygulamaya özel bir bölge ayırıcı ile) etrafında bir son çalışma yapmanız gerekir.