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 malloctahmin 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_FREEvb. 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 ' brkveri segmentini küçültmek için kullandınız veya eşdeğeri (günümüzde çok nadirdir) veya munmapeş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_FIXEDbir MADV_FREEsegment için onu çalın.)
Ancak çoğu program bir şeyleri doğrudan bellek sayfalarından ayırmaz; Onlar kullanmak malloctarzı ayırıcı. Aradığınızda free, ayırıcı, yalnızca freebir 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, PyStringnesneyi 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 malloced bölgede son kullanımdaki bloğu kaldırmanız gerekir ve o zaman bile gerçekleşmeyebilir.)
Eğer varsa yapmak free bir malloced bölgesini, bu bir sebep olmadığını bilmek munmapveya eşdeğeri (veya brk, sen iç durumu bilmek zorunda) mallocnasıl uygulandığı yanı sıra. Ve bu, diğerlerinin aksine, oldukça platforma özgüdür. (Ve yine, genellikle mallocbir mmapsegmentte 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. mallocBu bir veya daha fazla freearamayı 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 mallocve 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 mmapuygulama 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.