Eryksun hat Frage 1 beantwortet, und ich habe Frage 3 (das Original Nr. 4) beantwortet, aber jetzt beantworten wir Frage 2:
Warum werden insbesondere 50,5 MB veröffentlicht - auf welcher Menge wird veröffentlicht?
Worauf es basiert, ist letztendlich eine ganze Reihe von Zufällen in Python malloc, die sehr schwer vorherzusagen sind.
Erstens, je nachdem, wie Sie den Speicher messen, messen Sie möglicherweise nur Seiten, die tatsächlich dem Speicher zugeordnet sind. In diesem Fall wird der Speicher jedes Mal, wenn eine Seite vom Pager ausgetauscht wird, als "freigegeben" angezeigt, obwohl er nicht freigegeben wurde.
Oder Sie messen verwendete Seiten, die zugewiesene, aber nie berührte Seiten zählen (auf Systemen, die optimistisch zu viel zuweisen, wie z. B. Linux), zugewiesene, aber gekennzeichnete Seiten MADV_FREEusw.
Wenn Sie wirklich zugewiesene Seiten messen (was eigentlich nicht sehr nützlich ist, aber es scheint das zu sein, worüber Sie fragen) und Seiten wirklich freigegeben wurden, zwei Umstände, unter denen dies passieren kann: Entweder Sie ' Sie haben brkoder äquivalent verwendet, um das Datensegment zu verkleinern (heutzutage sehr selten), oder Sie haben munmapoder ähnlich verwendet, um ein zugeordnetes Segment freizugeben. (Theoretisch gibt es auch eine kleinere Variante zu letzterem, da es Möglichkeiten gibt, einen Teil eines zugeordneten Segments freizugeben - z. B. ihn MAP_FIXEDfür ein MADV_FREESegment zu stehlen, das Sie sofort entfernen).
Aber die meisten Programme ordnen Dinge nicht direkt aus Speicherseiten zu; Sie verwenden einen mallocAllokator. Wenn Sie aufrufen free, kann der Allokator Seiten nur dann an das Betriebssystem freigeben, wenn Sie gerade freedas letzte Live-Objekt in einem Mapping (oder auf den letzten N Seiten des Datensegments) sind. Ihre Anwendung kann dies auf keinen Fall vernünftigerweise vorhersagen oder sogar im Voraus erkennen, dass dies geschehen ist.
CPython macht dies noch komplizierter: Es verfügt über einen benutzerdefinierten 2-Ebenen-Objektzuweiser über einem benutzerdefinierten Speicherzuweiser malloc. (Siehe die Quelle Kommentar für eine ausführlichere Erklärung.) Und oben auf , dass auch bei der C - API - Ebene, viel weniger Python, Sie haben nicht einmal direkt steuern , wenn die Top-Level - Objekte freigegeben werden.
Wenn Sie also ein Objekt freigeben, woher wissen Sie, ob es Speicher für das Betriebssystem freigibt? Nun, zuerst müssen Sie wissen, dass Sie die letzte Referenz veröffentlicht haben (einschließlich aller internen Referenzen, von denen Sie nichts wussten), damit der GC sie freigeben kann. (Im Gegensatz zu anderen Implementierungen wird mindestens CPython die Zuordnung eines Objekts aufheben, sobald dies zulässig ist.) Dadurch werden normalerweise mindestens zwei Dinge auf der nächsten Ebene freigegeben (z. B. geben Sie für eine Zeichenfolge das PyStringObjekt und den Zeichenfolgenpuffer frei ).
Wenn Sie die Zuordnung eines Objekts aufheben, müssen Sie den internen Status des Objektzuordners sowie dessen Implementierung kennen, um zu wissen, ob die nächste Ebene die Freigabe eines Objektspeicherblocks aufhebt. (Es kann offensichtlich nur passieren, wenn Sie das letzte Element im Block freigeben, und selbst dann kann es nicht passieren.)
Wenn Sie die Zuordnung eines Objektspeicherblocks freeaufheben, müssen Sie den internen Status des PyMem-Allokators sowie dessen Implementierung kennen, um festzustellen, ob dies einen Aufruf verursacht . (Auch hier müssen Sie die Zuordnung des letzten verwendeten Blocks innerhalb einer malloced-Region aufheben , und selbst dann kann dies möglicherweise nicht passieren.)
Wenn Sie tun free eine malloced Region, wissen , ob dies ein verursacht munmapoder gleichwertig (oder brk), müssen Sie den internen Zustand der weiß malloc, und wie es umgesetzt wird . Und dieser ist im Gegensatz zu den anderen sehr plattformspezifisch. (Und wieder müssen Sie im Allgemeinen die Zuordnung der zuletzt verwendeten mallocinnerhalb eines mmapSegments freigeben, und selbst dann kann dies möglicherweise nicht passieren.)
Wenn Sie also verstehen möchten, warum genau 50,5 MB veröffentlicht wurden, müssen Sie dies von unten nach oben verfolgen. Warum wurde die mallocZuordnung von Seiten im Wert von 50,5 MB aufgehoben, wenn Sie einen oder mehrere freeAufrufe getätigt haben (wahrscheinlich etwas mehr als 50,5 MB)? Sie müssten die Ihrer Plattform lesen mallocund dann die verschiedenen Tabellen und Listen durchsuchen, um den aktuellen Status anzuzeigen. (Auf einigen Plattformen werden möglicherweise sogar Informationen auf Systemebene verwendet, die so gut wie unmöglich zu erfassen sind, ohne einen Schnappschuss des Systems zu erstellen, um sie offline zu überprüfen. Glücklicherweise ist dies jedoch normalerweise kein Problem.) Und dann müssen Sie Machen Sie dasselbe auf den 3 darüber liegenden Ebenen.
Die einzig nützliche Antwort auf die Frage lautet "Weil".
Sofern Sie keine ressourcenbeschränkte (z. B. eingebettete) Entwicklung durchführen, haben Sie keinen Grund, sich um diese Details zu kümmern.
Und wenn Sie eine ressourcenbeschränkte Entwicklung durchführen, ist es nutzlos, diese Details zu kennen. Sie müssen so ziemlich alle diese Ebenen und insbesondere mmapden Speicher, den Sie auf Anwendungsebene benötigen, beenden (möglicherweise mit einem einfachen, gut verstandenen, anwendungsspezifischen Zonenzuweiser dazwischen).