Speichergröße ermitteln

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Killigen
User
Beiträge: 48
Registriert: Freitag 6. März 2015, 10:46

Hallo Leute!

habe folgendes Problem: Ich möchte in Python größere Datenmengen Puffern. Meine Fragen hierbei:
1. Welche Größe fasst eine normale Variable in Python? 32 Bit?
2. Welche Größe fasst ein Array/Liste?
3. Wie kann man die Größe eines Arrays bestimmen?

Mir ist klar das man über

var = [1,4,5,66,"dfasfafsf","fasff",3]
print len(var)

die Anzahl der Elemente ermitteln kann, jedoch möchte ich wissen wie viel Speicher konkret im RAM verwendet wird um die Daten zu speichern. Gibt es dafür eine "sizeof" Funktion, die mir den konkreten Speicherbedarf zurückgibt?

Danke für die Unterstützung!

mfg Killigen
BlackJack

@Killigen: Die Frage lässt sich nicht wirklich beantworten.

Was ist eine „normale Variable“? In Python ist jeder Wert ein Objekt. In CPython wird für jedes Objekt eine C-Datenstruktur angelegt/verwendet. Wie gross die letztendlich ist, hängt auch vom System ab, wie viele Bytes dort beispielsweise ganze Zahlen (in C) oder Zeiger belegen und eventuell auch welche Ausrichtungen von Strukturfeldern vom Compiler vorgenommen werden.

Dann stellt sich aber auch die Frage bei Datenstrukturen ob da verschiedene Objekte drinstecken, oder teilweise Objekte mehrfach. Und ob Objekte auch ausserhalb der Datenstruktur ebenfalls verwendet werden. Wie soll so etwas dann bei der Grösse zählen?

Die ”Grundgrösse” eines Objekts kann man mit der `__sizeof__()`-Methode abfragen:

Code: Alles auswählen

In [2]: object().__sizeof__()
Out[2]: 8

In [3]: 42 .__sizeof__()
Out[3]: 12

In [4]: 'hallo'.__sizeof__()
Out[4]: 26
Killigen
User
Beiträge: 48
Registriert: Freitag 6. März 2015, 10:46

@BackJack:
Ich schildere mein genaues Problem: Ich habe eine Klasse. Diese enthält u.a. zwei Attribute (Listen). Von dieser Klasse werden im Programmablauf immer wieder neue Objekte erzeugt. Diese Objekte werden dann wiederum in einer Liste gepuffert. Diese Liste kann nun sehr groß werden. Aus diesem Grund möchte ich wissen welche Größe diese Liste im Speicher einnimmt. Um dem Problem eines RAM- Überlaufs entgegenzuwirken möchte ich die Informationen ab einer bestimmten Größe der Liste in ein externes File schreiben und die Liste dann wieder leeren, um den Speicher wieder freizugeben. Wie setze ich das am Besten um?

Zu der Methode __sizeof__():
Was soll man genau unter dem Begriff Grundgröße verstehen?
Was sagt die Zahl aus die man zurückbekommt? x Bit werden zum Speichern verwendet? Also für das Objekt 42 werden 12 Bit verwendet??? Kommt mir recht viel vor...
__deets__
User
Beiträge: 14528
Registriert: Mittwoch 14. Oktober 2015, 14:29

Es ist viel. Eine simple Zahl ist in Python trotzdem eine komplette PyObject-Struktur in C.

Mir klingt dein Problem eher antizipatorischer Natur. *Hast* du Speicherueberlaufsprobleme, oder glaubst du nur sie zu haben? Und wenn du sie hast, hast du eine Strategie, die besser ist, als das System swappen zu lassen? Nicht, dass das toll waere. Aber wenn du kein Kriterium hast, nach dem du die Daten partitionieren kannst, dann implementier das halt.
BlackJack

@Killigen: Wenn Dir 12 Bits schon viel vorkommt, dann möchtest Du vielleicht gar nicht wissen das das *Bytes* sind. ;-)

Grundgrösse heisst, das es nur das Objekt selbst betrifft und nicht Elemente oder Attribute. Eine Liste mit n Elementen liefert bei der Methode immer die gleiche Byteanzahl, egal wie viel Speicher die Elemente belegen:

Code: Alles auswählen

In [6]: [] .__sizeof__()
Out[6]: 20

In [7]: [1, 2, 3] .__sizeof__()
Out[7]: 32

In [8]: [1, 2, 'abcdefghijklmnopqrstuvwxyz'] .__sizeof__()
Out[8]: 32
DasIch
User
Beiträge: 2718
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

Man sollte auch Bedenken dass alles bisher gesagte nur auf CPython zutrifft. PyPy schaut sich z.B. den Inhalt von Listen und Dicts an und verwendet davon abhängig optimierte Implementationen die weniger Speicher verbrauchen. Dann bleibt aber immer noch der Speicherverbrauch des Interpreters selbst, der schon nicht unerheblich ist.

Wenn man ernsthaft soviel Wert auf den Speicherverbrauch legt, muss man schon seine Sprache dementsprechend wählen. Rust wäre vielleicht eine sinnvolle Wahl.
Killigen
User
Beiträge: 48
Registriert: Freitag 6. März 2015, 10:46

Also folgendes: Ich habe mich mit Kommilitonen unterhalten und bin zu dem Ergebnis gekommen das Ganze anders aufzuziehen. Und zwar werde ich den Speicherverbrauch meines gesamten Scripts verwenden, um anhand dessen quasi den "Cache" zu leeren. Hier meine Frage nun: Gibt es eine Möglichkeit über in-built Funktionen oder Bibliotheken den aktuellen Speicherverauch des kompletten Scripts zu erhalten?
Danke im Voraus!
BlackJack

@Killigen: Also man kann den Speicherverbrauch von Prozessen beispielsweise mit dem `psutils`-Modul abfragen, allerdings muss der Speicher der freigegeben wird, nicht zwangsläufig an das Betriebssystem zurückgegeben werden. Es kann also durchaus passieren dass das freigeben von den Objekten keinerlei Einfluss auf den vom Prozess verbrauchten Speicher hat.
Killigen
User
Beiträge: 48
Registriert: Freitag 6. März 2015, 10:46

Das heißt wenn ich bei einer Überschreitung meiner gedachten Begrenzung die Liste wieder leere kann es sein, dass der Speicherplatz trotzdem weiter belegt ist!? Und wenn ich die Liste im Anschluss erneut befülle wird zusätzlicher RAM benötigt?
BlackJack

@Killigen: Nein, denn Python bzw. die C-Laufzeitbibliothek weiss ja welcher Platz ”belegt” und welcher ”frei” ist. Dieses Konzept kann es halt auf mehreren Ebenen geben: Dem Betriebssystem, der C-Laufzeitbibliothek (`malloc()`/`free()`), und der Python-Laufzeitbibliothek. Und nur an die Informationen vom Betriebssystem kommt man über eine öffentliche Schnittstelle heran (AFAIK).
DasIch
User
Beiträge: 2718
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

Es gibt tracemalloc welches mit PEP 454 vorgeschlagen wurde. Das dürfte allerdings hier nur begrenzt hilfreich sein.
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Um nochmal auf __deets__ zurueckzukommen: Weisst du, ob du ein Speicherproblem hast? Wenn ja, wie sieht das aus?
Speicherschonend zu programmieren ist eine Sache, sich unnoetig Gedanken um ein moegliches Problem zu machen ist eine andere Sache.
Antworten