<div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div class="gmail_default" style="font-family:arial,helvetica,sans-serif"><span style="font-family:Arial,Helvetica,sans-serif">On Wed, Feb 27, 2019 at 9:59 PM Victor Stinner <<a href="mailto:vstinner@redhat.com">vstinner@redhat.com</a>> wrote:</span><br></div></div><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Maybe pickle is inefficient in its memory management and causes a lot<br>
of memory fragmentation?<br></blockquote><div><br></div><div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">No, it is not relating to pickle efficiency and memory fragmentation.</div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">This problem is happened because pymalloc doesn't have no hysteresis</div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">between map & unmap arenas.</div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">Any workload creating some objects and release them soon may affected</div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">by this problem.</div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif"><br></div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">When there are no free pool, pymalloc use  mmap to create new arena (256KB).</div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">pymalloc allocates new pools (= pages) from the arena.  It cause minor fault.</div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">Linux allocates real memory to the page and RSS is increased.</div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif"><br></div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">Then, when all objects newly created in the pool are destroyed, all pools in the</div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">arena are free.  pymalloc calls munmap() soon.</div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif"><br></div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">unpickle can be affected by this problem than pure Python because:</div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif"><br></div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">* unpickle is creating Python objects quickly.  fault overhead is relatively large.</div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">* Python code may creates junk memory block (e.g. cached frame object, freeslot, etc)</div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">  but C pickle code doesn't creates such junks.  So newly allocated pools are</div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">  freed very easily.</div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif"><br></div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">I think this issue can be avoided easily.  When arena is empty but the arena<br></div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">is head of usable_arenas, don't call munmap for it.</div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">I confirmed m2.py can't reproduce the issue with this patch.</div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif"><br></div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif"><div class="gmail_default">diff --git a/Objects/obmalloc.c b/Objects/obmalloc.c</div><div class="gmail_default">index 1c2a32050f..a19b3aca06 100644</div><div class="gmail_default">--- a/Objects/obmalloc.c</div><div class="gmail_default">+++ b/Objects/obmalloc.c</div><div class="gmail_default">@@ -1672,7 +1672,7 @@ pymalloc_free(void *ctx, void *p)</div><div class="gmail_default">      *    nfreepools.</div><div class="gmail_default">      * 4. Else there's nothing more to do.</div><div class="gmail_default">      */</div><div class="gmail_default">-    if (nf == ao->ntotalpools) {</div><div class="gmail_default">+    if (nf == ao->ntotalpools && ao != usable_arenas) {</div><div class="gmail_default">         /* Case 1.  First unlink ao from usable_arenas.</div><div class="gmail_default">          */</div><div class="gmail_default">         assert(ao->prevarena == NULL ||</div><div class="gmail_default"><br></div></div></div></div>-- <br><div dir="ltr" class="gmail_signature">INADA Naoki  <<a href="mailto:songofacandy@gmail.com" target="_blank">songofacandy@gmail.com</a>></div></div></div></div>