Die Speichernutzung des GC-Zielobjekts kann ab Python 3.7.4 um 8 Byte erhöht werden

Im x86-64-ABI sollen int128- und lange Doppeltypen an einer 16-Byte-Grenze platziert werden.

Die Pymalloc-Implementierung von Python ist jedoch so konzipiert, dass Speicherblöcke mit 8-Byte-Grenzen zurückgegeben werden. .. .. Bist du in Ordnung? Wenn Sie versuchen, eine Struktur zu mallocieren, die einen Typ enthält, der eine 16-Byte-Ausrichtung erfordert, sollte dies ein Vielfaches von 16 Byte sein, damit malloc (sizoef (Struktur)) sicher ist und malloc (Größe von (Struktur) + Anzahl der Bytes, die kein Vielfaches von 16 ist) ) Scheint in solchen Fällen ein Problem zu sein.

Je problematischer der GC-Header ist. Der GC-Header in einer 64-Bit-Umgebung beträgt 24 Byte. Wie der Name "Header" andeutet, wird er am Anfang von GC-Zielobjekten platziert (Objekte, aus denen möglicherweise Zirkelverweise bestehen, z. B. Tupel, Liste und Diktat).

Weisen Sie beim Erstellen eines GC-Zielobjekts Speicher wie "malloc (sizeof (GC-Header) + Objektgröße)" zu und verwenden Sie dann die vom GC-Header verschobene Adresse für einen Zeiger vom Typ "PyObject *". Selbst wenn malloc eine 16-Byte-Grenzadresse zurückgibt, wird das Python-Objekt unter der + 24-Byte-Adresse gespeichert. Wenn die Struktur des Objekts einen int128- oder langen Doppeltyp hat, wird es über die 16-Byte-Grenze platziert. Ich werde.

Es scheint, dass neuere Compiler tatsächlich Anweisungen verwenden, die 16-Byte-Grenzen annehmen, und anstatt "theoretisch zu verletzen, aber tatsächlich ohne Probleme zu arbeiten", ist das Problem "wirklich in Segfo zu fallen". Es ist geworden.

Ich habe dies bis vor kurzem nicht bemerkt, aber Python 2.7 hat dieses Verhalten früher gemeldet und 2.7.15 hat den GC-Header von 24 Byte auf 32 Byte erhöht. (Changelog, [Commit](https://github.com/python/cpython/ commit / 0b91f8a668201fc58fa732b8acc496caedfdbae0), issue)

Ein ähnliches Problem wurde kürzlich in Python 3.7 (Absturzproblem, [Altes Uansan-Fehlerproblem](https: //bugs.python.) Gemeldet. org / issue27987)) Es sieht also so aus, als müssten wir das gleiche Update anwenden, es sei denn, wir finden einen anderen guten Weg, um die ABI-Kompatibilität nicht zu beeinträchtigen. Für seltene Typen wie Long Double und Int128 ist es für mich, der dumm ist, bedauerlich, den Speicherverbrauch von Taples, die groß sind und diese Typen niemals enthalten, um +8 Byte erhöhen zu müssen.

Übrigens wird in Python 3.8 der Inhalt des GC-Headers von 3 Wörtern (24 Bytes in einer 64-Bit-Umgebung) auf 2 Wörter (16 Bytes in derselben) reduziert, und die Speichernutzung der GC-Zielobjekte str, bytes, int, float usw. wird auf 8 reduziert. Es gelang mir, den Biss zu schneiden. Daher ist es von diesem Problem nicht betroffen und es ist keine zusätzliche Polsterung erforderlich. Das Ergebnis ist eine Reduzierung um 16 Byte im Vergleich zu Python 2.7.15 oder höher und möglicherweise 3.7.4 oder höher. Ich bin wirklich froh, dass diese Verbesserung erfolgreich war.

Recommended Posts

Die Speichernutzung des GC-Zielobjekts kann ab Python 3.7.4 um 8 Byte erhöht werden
Schätzen Sie die Gesamtspeicherauslastung eines Objekts grob ab
Verwendung von Python-Einheimischen ()
Ermitteln Sie den Durchmesser des Diagramms anhand der Suche nach Breitenpriorität (Python-Speicher).
[Python] Richtige Verwendung der Karte
[Python] Wert des Funktionsobjekts (?)
Beispiel für die Verwendung von Python Pickle
Grundlegende Verwendung von Python-F-String
[Python] Richtige Verwendung von Join
Das Ausführen einer großen Anzahl von Python3 Executor.submit verbraucht möglicherweise viel Speicher.