ubuntuusers.de

Dateigröße auf HDD vs Dateigröße im RAM

Status: Gelöst | Ubuntu-Version: Ubuntu 11.10 (Oneiric Ocelot)
Antworten |

ubuntuboy

Avatar von ubuntuboy

Anmeldungsdatum:
19. März 2012

Beiträge: 17

Wohnort: /home/ubuntuboy

Hallo,

ich habe eine Datei mit einem Python Dictionary welche auf der Festplatte ca. 550MB belegt,
wenn ich diese in Python lade wächst der Arbeitsspeicher um ca. 6GB, das ist nach Adam Riese
eine Vergrößerung um Faktor ~10.9, woher kommt dieses Aufblähen ???.

Zur Info, bei der Datei handelt es sich um einen Invertierten Index welcher durchsucht werden soll,
im Vergleich zu einer Datenbank wie MySQL ist die Performance "Unmenschlich Geil" ☺

Bin über jeden Tip oder Link dankbar.

Grüße ubuntuboy

Kinch

Anmeldungsdatum:
6. Oktober 2007

Beiträge: 1261

im Vergleich zu einer Datenbank wie MySQL ist die Performance "Unmenschlich Geil"

Tja, jetzt weißt du auch warum. Wenn man genug Index-Strukturen anlegt, dann geht das Retrieval in den meisten Fällen sehr schnell, nur bezahlt man das mit einem deutlich gestiegenen Speicher-Verbrauch.

Bei so einem großen Dict, würde ich mir allerdings auch überlegen nicht so etwas wie redis zu verwenden.

ubuntuboy

(Themenstarter)
Avatar von ubuntuboy

Anmeldungsdatum:
19. März 2012

Beiträge: 17

Wohnort: /home/ubuntuboy

Overhead war mir ja irgendwie bewußt aber um den Faktor 10.

Bei so einem großen Dict, würde ich mir allerdings auch überlegen nicht so etwas wie redis zu verwenden.

Das mit dem redis verstehe ich nicht ganz denn ich nutze die Erweiterung nicht, es handelt sich um Dict welche in eine Textdatei geschrieben wurde und wieder eingelesen wird.

Das ist nur für mein Verständnis da ich gerade ein paar neue Ansätze gelernt habe,
leider wird dort nicht auf derlei Details eingegangen und ich bin noch nicht so lange mit Python unterwegs.

Ich habe die MySQL Daten einfach umgeformt und in das Dict / die Datei geschrieben.
Was die Größe angeht ich habe hier noch größere Indexe rumliegen und der Server hat auch noch genug Platz im Ram (16GB).
Ich war nur erschrocken wie groß die Daten wurden.

Grüße ubuntuboy

user_unknown

Avatar von user_unknown

Anmeldungsdatum:
10. August 2005

Beiträge: 17621

Wohnort: Berlin

ubuntuboy schrieb:

wenn ich diese in Python lade wächst der Arbeitsspeicher um ca. 6GB, das ist nach Adam Riese

im Vergleich zu einer Datenbank wie MySQL ist die Performance "Unmenschlich Geil" ☺

Einer Datenbank, der Du auch 6 GB spendierst?

Kinch

Anmeldungsdatum:
6. Oktober 2007

Beiträge: 1261

ubuntuboy schrieb:

Overhead war mir ja irgendwie bewußt aber um den Faktor 10.

Ich weiß nicht wie dicts in Python intern implementiert werden. Allgemein Skalieren Hash-maps aber nicht so gut, weil es immer das Problem mit Kollisionen gibt. Um das ganze Effizient zu machen, müssen die Kollisionen aufgelöst werden. Sowas kann eventuell deutlich schlimmer als Linear wachsen.

Bei so einem großen Dict, würde ich mir allerdings auch überlegen nicht so etwas wie redis zu verwenden.

Das mit dem redis verstehe ich nicht ganz denn ich nutze die Erweiterung nicht,

Welche Erweiterung? Redis ist eine Datenbank, die komplett im RAM läuft und auch ein Key-Value-Schema bereit stellt. Generell sollte man auch eine Datenbank passend zum Einsatzzweck wählen. Ein Key-Value-Schema ist in einer SQL-Datenbank auch nicht so gut aufgehoben.

leider wird dort nicht auf derlei Details eingegangen und ich bin noch nicht so lange mit Python unterwegs.

Solche Internas sind auch meistens nicht dokumentiert, weil das Implementierungsabhängig ist und nicht in den Sprachbericht kommen. Weiß nicht, ob man zu cpython etwas findet. Eventuell mal googeln.

Was die Größe angeht ich habe hier noch größere Indexe rumliegen und der Server hat auch noch genug Platz im Ram (16GB).

Ja, aber vorsicht: Du kannst nicht davon ausgehen, dass es pauschal einen Faktor 10 gibt, um den das Dict größer ist. Wenn es Quadratisch wächst, kannst du bei einer 1 GB Datei plöztlich mehrere dutzend GB-RAM-Verbrauch haben. Bei solchen Spielchen würde ich mir ein hartes RAM-Limit setzten, weil eine Linux-Kiste schnell mal unbrauchbar wird, wenn man den RAM sprengt.

ubuntuboy

(Themenstarter)
Avatar von ubuntuboy

Anmeldungsdatum:
19. März 2012

Beiträge: 17

Wohnort: /home/ubuntuboy

user unknown schrieb:

Einer Datenbank, der Du auch 6 GB spendierst?

Nein !, aber ich find die Performance "Geil", ist ja vielleicht eine simple Sache aber für mich das erste mal 😉

Kinch

Welche Erweiterung? Redis ist eine Datenbank, die komplett im RAM läuft und auch ein Key-Value-Schema bereit stellt. Generell sollte man auch eine Datenbank passend zum Einsatzzweck wählen. Ein Key-Value-Schema ist in einer SQL-Datenbank auch nicht so gut aufgehoben.

Da habe ich mich nicht korrekt ausgedrückt (Sorry!), ich habe aber auch erst nach deinem ersten Post etwas über Redis gelesen, Redis war mir vorher nicht bekannt. Was die korrekte Datenbank angeht, ich habe das ganze Spiel auch nur zum testen gebaut, bin halt auf diesen scheinbar dummen Gedanken gekommen.

Ja, aber vorsicht: Du kannst nicht davon ausgehen, dass es pauschal einen Faktor 10 gibt, um den das Dict größer ist. Wenn es Quadratisch wächst, kannst du bei einer 1 GB Datei plöztlich mehrere dutzend GB-RAM-Verbrauch haben. Bei solchen Spielchen würde ich mir ein hartes RAM-Limit setzten, weil eine Linux-Kiste schnell mal unbrauchbar wird, wenn man den RAM sprengt.

Definiere bitte "schnell mal unbrauchbar wird". (Das macht mir ein wenig Angst)

Mich hat das halt gewundert, ich bin von einem max Faktor von 2,5 ausgegangen, mir fehlen aber definitiv die Erfahrungswerte bzw. das Wissen.

Edit:

Und das versteckte "RTFM" finde ich gut, ich werde es beherzigen 😉
Naja bei genauerer Betrachtung fällt schon am Thread-Titel auf was bei hier falsch gelaufen ist, Asche über mein Haupt.
Googlen nach "python dictionary ram" bringt mir → http://stackoverflow.com/questions/671403/memory-efficiency-one-large-dictionary-or-a-dictionary-of-smaller-dictionaries

ubuntuboy

(Themenstarter)
Avatar von ubuntuboy

Anmeldungsdatum:
19. März 2012

Beiträge: 17

Wohnort: /home/ubuntuboy

Und hier noch kurz die Lösung meines Problems.

Fehlerhafter Code (naja funktionieren tut er ja, bringt aber nicht das gewünschte Ergebnis)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
def dump_data(data, filename):
	db = open(filename, 'wb')
	db.write(str(data))
	db.close()		

def load_data(filename):
	db = open(filename, 'rb')
	data = eval(db.read())
	db.close()
	return data

Also ich habe das Dictionary via dump_data in eine Datei geschrieben und mittels load_data wieder geladen.(Exceptions wurden absichtlich weggelassen)
Und hier liegt das Problem, load_data führt ein eval aus um die Daten wieder zum Dictionary zu machen, nach Studium von "cpython/python" bin ich auf "cPickle"
aufmerksam geworden. cPickle serialisiert die Daten und schreibt sie in eine Datei, von welcher man sie dann auch wieder laden kann.
So wurden aus ~550MB Daten auf der Platte nur ~55MB und im Speicher wurden die Daten von ~6GB auf ~200MB geschrumpft.
So kann ich damit gut Leben, und mich trozdem der "Unmenschlich Geilen" Performance erfreuen ☺.

Hier der berichtigte Code mit cPickle

1
2
3
4
5
6
def dump_data(data, filename):
	cPickle.dump(data, open(filename, "wb"), -1)

def load_data(filename):
	data = cPickle.load(open(filename, "rb"))
	return data

Danke Kinch du hast mich in die richtige Richtung gestoßen !

Grüße ubuntuboy

Kinch

Anmeldungsdatum:
6. Oktober 2007

Beiträge: 1261

Nur ein kleiner Hinweis:

def dump_data(data, filename):
	db = open(filename, 'wb')
	db.write(str(data))
	db.close()

Das Idiom kann auch durch folgendes abgelöst werden:

def dump_data(data, filename):
	with open(filename,'wb') as db:
                db.write(str(data))

Das With-Statement hat den wichtigen Vorteil, dass es das Schließen der Datei garantiert, egal ob exception geworfen wurden oder nicht. Außerdem kann man nicht versehentlich das Schließen vergessen.

def dump_data(data, filename):
	cPickle.dump(data, open(filename, "wb"), -1)

Schließt pickle den Filehandler? Wenn nicht, dann bleibt der hier offen, bis der GC ihn schließt. Habe schon von einigen Pythonern gehört, dass sie Dateien nicht selbst schließen, sondern auf den GC vertrauen. Aber ich bin mir nicht so sicher, das eine gute Idee ist.

Antworten |