RAM verbrauchsproblem Postgresql+ZEOS

Für Themen zu Datenbanken und Zugriff auf diese. Auch für Datenbankkomponenten.
Dragon
Beiträge: 162
Registriert: Mi 31. Jul 2013, 15:07
OS, Lazarus, FPC: Ubuntu 16.04, CodeTyphon 5.80

RAM verbrauchsproblem Postgresql+ZEOS

Beitrag von Dragon »

Hallo liebe Lazarus community ich habe folgendes Problem und zwar wenn ich Daten in die datenbank schreibe(Postgresql) verbraucht das programm mit der Zeit immer mehr ram und zwar abartig viel zum vergleich ich ue eine ~420KB textdatei rein und der Ramverbrauch ist am Zyklusende ca 55-65MB vorm freigeben der Stringlist, und danach imernoch ca 50MB und das skaliert exponenziell mit der inputgröße mache ich was falsch?

Code: Alles auswählen

procedure TForm1.Button2Click(Sender: TObject);
var
  i: qword;
  Origin: string;
  sl: TStringList;
begin
  ZQuery1.Close();
  ZQuery1.SQL.Clear;
  ZQuery1.SQL.Add('CREATE TABLE IF NOT EXISTS dict ( id SERIAL PRIMARY KEY , word varchar(512) NOT NULL);');
  ZQuery1.SQL.Add('CREATE TABLE IF NOT EXISTS stats ( w1 INTEGER NOT NULL REFERENCES dict(id), w2 INTEGER NOT NULL REFERENCES dict(id), fw INTEGER NOT NULL REFERENCES dict(id), az INTEGER NOT NULL, PRIMARY KEY (w1, w2, fw));');
  ZQuery1.SQL.Add('CREATE UNIQUE INDEX ON dict(word);');
  ZQuery1.Open;
  ZQuery1.ExecSQL;
 
 
  Origin := Loadfile('./testfile');
  Origin := Stringreplace(Origin, '''', '''' + '''', [rfReplaceAll]);
  sl := TStringList.Create;
  sl.Delimiter := ' ';
  sl.QuoteChar := #$0;
  sl.DelimitedText := Origin;
  for i := 0 to sl.Count - 1 do
  begin
    ZQuery1.SQL.Clear;
    ZQuery1.SQL.Add('INSERT INTO dict (word) VALUES (''' + sl[i] + ''') ON CONFLICT DO NOTHING;');
    ZQuery1.ExecSQL;
 
   // Das sollte Batch insert werden
   // if i mod 1000 = 0 then
   // begin
   //   ZConnection1.Commit;
   // end;
 
    Form1.Caption := IntToStr(i);
  end;
  sl.free;
end;

Dragon
Beiträge: 162
Registriert: Mi 31. Jul 2013, 15:07
OS, Lazarus, FPC: Ubuntu 16.04, CodeTyphon 5.80

Re: RAM verbrauchsproblem Postgresql+ZEOS

Beitrag von Dragon »

Schade niemand eine Antwort, ich hab bis jetzt leider auch keine lösung gefunden

wp_xyz
Beiträge: 4869
Registriert: Fr 8. Apr 2011, 09:01

Re: RAM verbrauchsproblem Postgresql+ZEOS

Beitrag von wp_xyz »

Sieht nach einem Speicherleck aus, wobei dein geposteter Code aber in Ordnung zu sein scheint. Hast du schon heaptrc probiert? Unter "Projekteinstellungen" / "Compilereinstellungen" / "Debuggen" ein Häkchen bei "HeapTrc-Unit verwenden" setzen. Du erhältst dann beim Programm-Ende eine Auflistung aller Speicherblöcke, die nicht freigegeben wurden und in welcher Zeile sie angefordert wurden. Steht in der Meldung "Unfreed memory blocks: 0", ist bzgl. Speicherlecks alles in Ordnung.

50 MB Speicheranforderung ist heutzutage gar nichts. Wenn du die Routine ein zweites Mal aufrufst, wird es dann nochmals mehr, oder verwendet sie den vom 1.Mal freigegebenen Speicher?

Dragon
Beiträge: 162
Registriert: Mi 31. Jul 2013, 15:07
OS, Lazarus, FPC: Ubuntu 16.04, CodeTyphon 5.80

Re: RAM verbrauchsproblem Postgresql+ZEOS

Beitrag von Dragon »

Nein Heaptrace hatte ich noch nicht probiert werde ich gleich mal machen.

Es geht mir im Endeffekt nicht darum das es 50MB brauch oder hundert, das was mir so suspekt erscheint ist ein verbrauch in einer derartigen höhe bei so geringem input.

Edit:
Heap dump by heaptrc unit
57305622 memory blocks allocated : 43306647267/43381202224
57305622 memory blocks freed : 43306647267/43381202224
0 unfreed memory blocks : 0
True heap size : 1966080
True free heap : 1966080

Edit2:
starten tuts mit ~14Mb nach dem starten der Procedure steigt es an bis ca55-65MB nach dem freigeben sinds ~47MB aber bei erneutem ausführen steigt es trotzdem nur bis ~62MB an auch bei weiteren wiederhohlungen

wp_xyz
Beiträge: 4869
Registriert: Fr 8. Apr 2011, 09:01

Re: RAM verbrauchsproblem Postgresql+ZEOS

Beitrag von wp_xyz »

Dann ist alles in Ordnung. Was letzendlich genau passiert, kann ich nicht sagen, aber prinzipiell hängt der anfängliche Speicherzuwachs damit zusammen, nach welcher Strategie der Speichermanager den angeforderten Speicher zur Verfügung stellt und zurückgegebenen Speicher wieder verfügbar macht. Einfach ausgedrückt, stell dir vor, du forderst zweimal eine bestimmte Menge Speicher an. Wenn du jetzt den zuerst angeforderten Speicher freigibst, hast du eine Lücke im Heap. Wird bei einer dritten Anforderung, sagen wir, die doppelte Menge Speicher angefordert, kann dieser Block nicht die freigegebene Lücke belegen, weil diese zu klein ist, so dass ingesamt immer weniger Speicher verfügbar ist. Erst wenn alle Speicherblöcke freigegeben sind, hat man keine Lücken mehr. Wenn dann dieselbe Prozedur erneut aufgerufen wird, wiederholt sich das Spielchen. Natürlich nur, wenn zwischenzeitlich keine anderen Routinen ihrerseits weitere Lücken hinterlassen haben. Noch komplizierter wird's, wenn du den Verlauf der Speichernutzung im Taskmanager von Windows verfolgst, weil dort auch der von anderen Anwendungen belegte Speicher eingeht.

Dragon
Beiträge: 162
Registriert: Mi 31. Jul 2013, 15:07
OS, Lazarus, FPC: Ubuntu 16.04, CodeTyphon 5.80

Re: RAM verbrauchsproblem Postgresql+ZEOS

Beitrag von Dragon »

Ich nutze Linux^^ aber trotzdem woher kommt soeine datenmenge das kann doch nicht irg deklarationsoverheat sein oder doch bei so geringer inputdatenmenge.

wp_xyz
Beiträge: 4869
Registriert: Fr 8. Apr 2011, 09:01

Re: RAM verbrauchsproblem Postgresql+ZEOS

Beitrag von wp_xyz »

Du weißt natürlich nicht, was postgresql im Detail alles macht. Vielleicht findest du in deren Docs Konfigurationswerte, die du in die Params der Connection schreiben kannst. Kannst du's mal mit einem schlankeren Datenbank-System wie sqlite3 probieren?

Dragon
Beiträge: 162
Registriert: Mi 31. Jul 2013, 15:07
OS, Lazarus, FPC: Ubuntu 16.04, CodeTyphon 5.80

Re: RAM verbrauchsproblem Postgresql+ZEOS

Beitrag von Dragon »

SQLite hatte ich schon probiert war nur viel!! zu langsam

SQLite ~25-30min
Postgresql ~2-5min
für den Testdatensatz

Christian
Beiträge: 6079
Registriert: Do 21. Sep 2006, 07:51
OS, Lazarus, FPC: iWinux (L 1.x.xy FPC 2.y.z)
CPU-Target: AVR,ARM,x86(-64)
Wohnort: Dessau
Kontaktdaten:

Re: RAM verbrauchsproblem Postgresql+ZEOS

Beitrag von Christian »

Hast du mal probiert ne Transaction zu benutzen ?
W.m.k.A.h.e.m.F.h. -> http://www.gidf.de/

Socke
Lazarusforum e. V.
Beiträge: 3158
Registriert: Di 22. Jul 2008, 19:27
OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 10/Linux/Raspbian/openSUSE
CPU-Target: 32bit x86 armhf
Wohnort: Köln
Kontaktdaten:

Re: RAM verbrauchsproblem Postgresql+ZEOS

Beitrag von Socke »

Dragon hat geschrieben:SQLite hatte ich schon probiert war nur viel!! zu langsam

SQLite ~25-30min
Postgresql ~2-5min
für den Testdatensatz

Das verwundert mich nicht bei deinem Code. Setze deine Insert-Anweisung innerhalb einer Transaction und schon sollte SQLite wesentlich schneller sein als die angegebenen 25-30 Minuten.

Außerdem solltest du den Wert nicht direkt in das SQL-Statement einbauen sonder per Parameter übergeben.
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein

Dragon
Beiträge: 162
Registriert: Mi 31. Jul 2013, 15:07
OS, Lazarus, FPC: Ubuntu 16.04, CodeTyphon 5.80

Re: RAM verbrauchsproblem Postgresql+ZEOS

Beitrag von Dragon »

Das war nur mein postgresql code mein SQLite code ist folgender

Code: Alles auswählen

procedure TForm1.Button1Click(Sender: TObject);
var
  i: qword;
  Origin: string;
  sl: TStringList;
begin
  SQLite3Connection1.DatabaseName := './DB.sqlite';
  SQLTransaction1.Database := SQLite3Connection1;
  SQLite3Connection1.Open;
  if SQLite3Connection1.Connected then
    Form1.Caption := 'Verbindung hergestellt';
  SQLQuery1.Transaction := SQLTransaction1;
 
  //Erzeugt Wörterbuchliste
  SQLQuery1.SQL.Text := 'CREATE TABLE IF NOT EXISTS tblDictonary (ID INTEGER Primary KEY, Wort VARCHAR(255) UNIQUE ON CONFLICT IGNORE);';
  SQLQuery1.ExecSQL;
  SQLTransaction1.commit;
 
 
  Origin := Loadfile('./test');
  Origin := Stringreplace(Origin, '"', '', [rfReplaceAll]);
  sl := TStringList.Create;
  sl.Delimiter := ' ';
  sl.QuoteChar := #$0;
  sl.DelimitedText := Origin;
  SQLQUERY1.Close;
  for i := 0 to sl.Count - 1 do
  begin
    SQLQuery1.SQL.Text := 'INSERT INTO tblDictonary (Wort) VALUES ("' + sl[i] + '")';
    SqlQuery1.ExecSQL;
    SqlTransaction1.Commit;
    Form1.Caption := IntToStr(i);
  end;
 
  SQLQuery1.Close;
end;


Edit:
Das ist übrigens mein Testfile
http://www.gutenberg.org/cache/epub/910/pg910.txt

Dragon
Beiträge: 162
Registriert: Mi 31. Jul 2013, 15:07
OS, Lazarus, FPC: Ubuntu 16.04, CodeTyphon 5.80

Re: RAM verbrauchsproblem Postgresql+ZEOS

Beitrag von Dragon »

So ich habe nochmal einwenig mit SQLite rumgespielt und nun klappt es wesentlich schneller
Speedimprovment hoch :D
8sec ca statt 30min ^^

Code: Alles auswählen

for i := 0 to sl.Count - 1 do
  begin
    SQLQuery1.SQL.Text := 'INSERT INTO tblDictonary (Wort) VALUES ("' + sl[i] + '")';
    SqlQuery1.ExecSQL;
    //SqlTransaction1.Commit;
     if i mod 1000 = 0 then
     begin
       SqlTransaction1.Commit;
       Form1.Caption := IntToStr(i);
     end;
  end;

wp_xyz
Beiträge: 4869
Registriert: Fr 8. Apr 2011, 09:01

Re: RAM verbrauchsproblem Postgresql+ZEOS

Beitrag von wp_xyz »

Und wie sieht's mit dem Speicherzuwachs aus? Mache in dem Test bitte den Klammerwert bei VARCHAR() ebenfalls zu 512, so wie bei postgresql - ich würde nicht darauf schwören, dass die DB-Engines trotz des "VAR" nicht vielleicht doch feste 512 Byte anfordern, zumindest temporär (bei einer durchschnittlichen Wortgröße von 10 Zeichen und 420 kB pro Datei hättest du etwa 40.000 Wörter. Wenn jedes beim Speichervorgnag 512 Byte = 0.5 kB benötigt, hättest du schon mal 40.000 * 0.5 kB = 20 MB zusammen...)

Dragon
Beiträge: 162
Registriert: Mi 31. Jul 2013, 15:07
OS, Lazarus, FPC: Ubuntu 16.04, CodeTyphon 5.80

Re: RAM verbrauchsproblem Postgresql+ZEOS

Beitrag von Dragon »

Nein macht keinen unterschied das einzige was mir aufällt ist das der ramverbrauch mit der DB größe skaliert wenn ich weitere testdatein anlege in der SQLite DB(verwende bei SQLite übr Lazarus eigene DB nich ZEOS).
Lädt er die DB jedesmal vollständig in den RAM? Klingt mir doch eher unwahrscheinlich.

Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 6199
Registriert: So 7. Jan 2007, 10:20
OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
CPU-Target: 32Bit (64Bit)
Wohnort: Burgenland
Kontaktdaten:

Re: RAM verbrauchsproblem Postgresql+ZEOS

Beitrag von af0815 »

Dragon hat geschrieben:Lädt er die DB jedesmal vollständig in den RAM? Klingt mir doch eher unwahrscheinlich.

Warum nicht, bei so ner kleinen DB. Sorry aber 20 MB sind ja lachhaft.
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

Antworten