performanceproblem while schleife

Für Fragen zur Programmiersprache auf welcher Lazarus aufbaut
gocher
Beiträge: 298
Registriert: Di 23. Nov 2010, 23:41
OS, Lazarus, FPC: Ubuntu/Win, Lazarus trunk, FPC trunk
CPU-Target: 32Bit/64Bit
Wohnort: Geldern
Kontaktdaten:

Re: performanceproblem while schleife

Beitrag von gocher »

Dragon hat geschrieben:wieso rechnest du bei der stringliste in der schleife -3.
und kann man da überhaupt mit einer stringliste arbeiten ich meine muss dann jedes wort nicht in einer extra zeil vorliegen?


habe ich nun im Code erklärt
MfG Gocher
akt. Projekt: Webserver(HTTPS HTTP/2) mit integrierten CMS in Free Pascal - www.gocher.me

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

Re: performanceproblem while schleife

Beitrag von Dragon »

Edit1:
    Danke für die erweiterten kommentare
    habs so mal probiert das programm crasht dann aber mit "EStringListError: List index (416) out of bounds"


hab mich mal eben selbst qequotet weil ich übersehen hab das es schon eine dritte seite gab^^

Edit1:
Habe nochmal komplett sauber rekompiliert der fehler tritt nun nicht mehr auf

Edit2:
habs mal mit einer größeren datei probiert 11470Wörter(78kB) die ist unparsbar
dann nehme ich einfach kleinere dateien


Danke für eure hilfe

gocher
Beiträge: 298
Registriert: Di 23. Nov 2010, 23:41
OS, Lazarus, FPC: Ubuntu/Win, Lazarus trunk, FPC trunk
CPU-Target: 32Bit/64Bit
Wohnort: Geldern
Kontaktdaten:

Re: performanceproblem while schleife

Beitrag von gocher »

TStringList ist meines Wissens auf 134.217.728 Strings begrenzt (MaxListSize)
MfG Gocher
akt. Projekt: Webserver(HTTPS HTTP/2) mit integrierten CMS in Free Pascal - www.gocher.me

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

Re: performanceproblem while schleife

Beitrag von Dragon »

Und wie siehts mit der max größe von einem array aus

edit: das problem ist jetzt nur noch, wenn ich ein zweites file lade, überschreibt es das erste, hab zweimal das selbe file geladen, ergo müsste sich die anzahl bei allen verdoppeln, tut sie aber nicht die anzahl bleibt gleich

gocher
Beiträge: 298
Registriert: Di 23. Nov 2010, 23:41
OS, Lazarus, FPC: Ubuntu/Win, Lazarus trunk, FPC trunk
CPU-Target: 32Bit/64Bit
Wohnort: Geldern
Kontaktdaten:

Re: performanceproblem while schleife

Beitrag von gocher »

Wie sehen eigentlich deine Variablen-Deklarationen aus?
An welcher Stelle lädst Du die Datei, wie sieht dein kompletter Code aus?
Zuletzt geändert von gocher am So 15. Mai 2016, 16:40, insgesamt 1-mal geändert.
MfG Gocher
akt. Projekt: Webserver(HTTPS HTTP/2) mit integrierten CMS in Free Pascal - www.gocher.me

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

Re: performanceproblem while schleife

Beitrag von Dragon »

zurzeit noch so

Code: Alles auswählen

var
    database: array of Statistiken;
    content: string;
    s: string;
    //Analyse der Textlänge
    Text: string;
    Anzahl: longint;
    sanzahl: string;
 
    //Allgemeine schleifenzähler
    i: integer;
    i2: integer;
    //DAtenbank befüllung
    Prozent: single;
    sProzent: string;
    step: single;
 
    found: boolean;
    //  w : byte;
    //wort : array[1..3] of string;
    sl: TStringList;
 
    //wort1, wort2, folgewort: string;
    start, T1, T2, t3: word;
  begin

muss nr noch den alten kram rauswerfen wenn alles klappt wie es soll

Das wäre das record

Code: Alles auswählen

type
  Statistiken = record
    Wort1: string;
    Wort2: string;
    Folgewort: string;
    Anzahl: word;
    Vorkommen: byte;
  end;

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

Re: performanceproblem while schleife

Beitrag von Dragon »

Es ist teil einer .so das wäre hier die kompklette procedure

Code: Alles auswählen

 procedure MessageProc(AUser: PChar; AChannel: PChar; AMessage: PChar);
  var
    database: array of Statistiken;
    content: string;
    s: string;
    //Analyse der Textlänge
    Text: string;
    Anzahl: longint;
    sanzahl: string;
 
    //Allgemeine schleifenzähler
    i: integer;
    i2: integer;
    //DAtenbank befüllung
    Prozent: single;
    sProzent: string;
    step: single;
 
    found: boolean;
    //  w : byte;
    //wort : array[1..3] of string;
    sl: TStringList;
 
    //wort1, wort2, folgewort: string;
    start, T1, T2, t3: word;
  begin
    Content := AMessage;
 
    //Datenbankgeneriereung
    if AnsiStartsText('!markov add ', Content) then
    begin
      s := Copy(Content, 13, length(Content));
      //Lade text und zähle wörter
      Text := Loadfile('./markovtexte/' + s);
      Anzahl := Wordcount(Text);
      writeln(anzahl);
      sanzahl := IntToStr(Anzahl);
      irc.say(Achannel, PChar('Woerter im zu einlesendem text ' + sAnzahl));
 
      i := 1;
      sl := TStringList.Create;
      sl.Delimiter := ' '; // Leerzeichen als Wort Trenner
      sl.QuoteChar := #$0; // keine " als Maskierung
      sl.DelimitedText := Text;  // durch diese Zuordnung wird der Zugewiesene Text in einzelne Strings
      // (Worte in diesem Fall unterteilt)
      // dann kannst du dir alles ausschneiden ersparen
      for i := 0 to sl.Count - 3 do
        // die Schleife beginnt bei 0 (erstes Wort) und aus den letzten zwei Worten kannst Du keine
        // dreierkombinationen machen das würde zu Zugriffsverletzungen führen
      begin
        found := False;
        if length(Database) > 0 then
        begin
          for i2 := 0 to length(Database) - 1 do
          begin
            if (Database[i2].Wort1 = sl.strings[i]) and (Database[i2].Wort2 = sl.strings[i + 1]) and (Database[i2].Folgewort = sl.strings[i + 2]) then
            begin
              Inc(Database[i2].Anzahl);
              found := True;
              break;
            end;
          end;
        end;
        if not found then
        begin
          t2 := length(Database);
          Setlength(Database, t2 + 1);
          Database[t2].Wort1 := sl.strings[i];
          Database[t2].Wort2 := sl.strings[i + 1];
          Database[t2].Folgewort := sl.strings[i + 2];
          Database[t2].Anzahl := 1;
        end;
      end;
      sl.Free;
      Writeln(database[1].wort1 + database[1].wort2 + database[1].folgewort); writeln(Database[1].anzahl);
      Writeln(database[2].wort1 + database[2].wort2 + database[2].folgewort); writeln(Database[2].anzahl);
      Writeln(database[3].wort1 + database[3].wort2 + database[3].folgewort); writeln(Database[3].anzahl);
      Writeln(database[4].wort1 + database[4].wort2 + database[4].folgewort); writeln(Database[4].anzahl);
      //Baue satzvergleichsdatenbank auf
 
 
      //Berechne wahrscheinlichkeiten
 
    end
Zuletzt geändert von Dragon am So 15. Mai 2016, 17:09, insgesamt 1-mal geändert.

gocher
Beiträge: 298
Registriert: Di 23. Nov 2010, 23:41
OS, Lazarus, FPC: Ubuntu/Win, Lazarus trunk, FPC trunk
CPU-Target: 32Bit/64Bit
Wohnort: Geldern
Kontaktdaten:

Re: performanceproblem while schleife

Beitrag von gocher »

Code: Alles auswählen

var
 
//    start, T1, T2 : word; // word 0 .. 65535
    T2: Cardinal;
 

sonst ist dein Array auf 65536 Einträge beschränkt

Byte 0 .. 255
Shortint -128 .. 127
Smallint -32768 .. 32767
Word 0 .. 65535
Integer either smallint or longint
Cardinal longword
Longint -2147483648 .. 2147483647
Longword 0 .. 4294967295
Int64 -9223372036854775808 .. 9223372036854775807
QWord 0 .. 18446744073709551615

Ich kenne Deine Datei nicht wenn Du nur die Worte brauchts musst du sowieso vorher ".", ",", "!", ";", ... durch Leerzeichen ersetzen und doppelte Leerzeichen zusammenführen. Da könntest Du dann eventuell noch andere Anpassungen vornehem.

!!! Wenn die Funktion mehrfach aufgerufen werden soll und das Array (Datenbank) sich immer erweitern soll, sollte natürlich das Array keine lokale Variable sein!

Int64 verschenkt ein Bit, negative Wortanzahlen gibt es nicht :D , dann kannst Du auch gleich QWord nehmen belegt genau so viel PLatz im Speicher. QWord sind 8Byte! Parst Du die Bibel :shock:
18.446.744.073.709.551.615 = 18 Trillionen 446 Billiarden 744 Billionen 73 Milliarden 709 Millionen 551 Tausend 615
lass Dir das mal auf der Zunge zergehen :mrgreen:

!!! T2 ist immer noch etwas klein für die Bibel!

Beachte die !!! , ich muss mich nun ausklinken mein Hund sieht mich so verliebt an ich glaube er muss Gassi.
Hat Spass gemacht!
Zuletzt geändert von gocher am So 15. Mai 2016, 17:23, insgesamt 9-mal geändert.
MfG Gocher
akt. Projekt: Webserver(HTTPS HTTP/2) mit integrierten CMS in Free Pascal - www.gocher.me

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

Re: performanceproblem while schleife

Beitrag von Dragon »

ok ,danke parsbar ist die datei aber immernoch nicht.
entweder liegt es daran das die datei nichtasciizeichen enthält oder sie ist selbst für cardinal zu lang

Edit:
    Hab das Bottleneck gefunden, die Wordcountfunktion am Anfang war das Poblem und hab jetzt einen int64 genommen.
    Testfile 2 lässt sich nun ebenfalls parsen :)
    danke

Edit2:
    Wenn der die satzzeichen an den worten berhält ist das sogar glaube besser

Edit3:
    gibs eig eine möglichkeit ein integer mit unbegrenzter größe zu haben, die strings sind ja auch meine ich unendlich groß.
    Was ist die max größe von einem array of record bzw einem (dyn)array

Edit4:
    Hab mal aus meinem einen Vorheriegen Post, den ganzen alten Code rausgeworfen der übersichtkeithalber

Edit5:

Edit6:
    nein ich parse nicht die bibel^^

Edit7:
    Viel spaß beim gassi gehen und danke für deine ganze hilfe

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

Re: performanceproblem while schleife

Beitrag von Dragon »

Ich grabe diesen Thread nochmal aus weil ich an gochers Code nochmal Veränderungen vorgenommen habe. Dies habe ich gemacht weil mir ein wesentlich besserer weg eingefallen ist, um die menge der Informationen besser zu speichern um die Verarbeitung und Analyse zu vereinfachen.
Dazu lege ich jetzt nicht mehr nur ein Doppelpaar an + das entsprechende Folgewort, sondern nur noch einmal ein Doppelwortpaar und das Folgewort als Array sowie Anzahl & vorkommen, um somit Redundanzen der Doppelpaare zu sparen. doch irg funktioniert da noch nicht richtig und ich hab keineIdee wie ich das fixen könnte

Und noch eine unabhängige frage ich habe gehört das packed records kleiner sind wieso ist dies der Fall wird der Inhalt dann komprimiert?

Code: Alles auswählen

type
  Statistiken = record
    Wort1: string;
    Wort2: string;
    Folgewort: array of string;
    Anzahl: array of integer;
    Vorkommen: array of byte;
  end;
 
var
  database: array of Statistiken;
 

Code: Alles auswählen

  procedure MessageProc(AUser: PChar; AChannel: PChar; AMessage: PChar);
   var
   // database: array of Statistiken;
    content: string;
    s: string;
    //Analyse der Textlänge
    Text: string;
 
    //Allgemeine schleifenzähler
    i: integer;
    i2: integer;
    i3: integer;
 
    found: boolean;
    sl: TStringList;
 
    t2 : qword;
  begin
    Content := AMessage;
 
    //Datenbankgeneriereung
    if AnsiStartsText('!markov add ', Content) then
    begin
      s := Copy(Content, 13, length(Content));
      //Lade text und zähle wörter
      Text := Loadfile('./markovtexte/' + s);
      {Anzahl := Wordcount(Text);
      writeln(anzahl);
      sanzahl := IntToStr(Anzahl);
      irc.say(Achannel, PChar('Woerter im zu einlesendem text ' + sAnzahl));}

 
      i := 1;
      sl := TStringList.Create;
      sl.Delimiter := ' '; // Leerzeichen als Wort Trenner
      sl.QuoteChar := #$0; // keine " als Maskierung
      sl.DelimitedText := Text;  // durch diese Zuordnung wird der Zugewiesene Text in einzelne Strings
      // (Worte in diesem Fall unterteilt)
      // dann kannst du dir alles ausschneiden ersparen
      for i := 0 to sl.Count - 3 do
        // die Schleife beginnt bei 0 (erstes Wort) und aus den letzten zwei Worten kannst Du keine
        // dreierkombinationen machen das würde zu Zugriffsverletzungen führen
      begin
        found := False;
        if length(Database) > 0 then
        begin
 
          //Überprüft nach vorhandensein von doppelpaaren
          for i2 := 0 to length(Database) - 1 do
          begin
            if (Database[i2].Wort1 = sl.strings[i]) and (Database[i2].Wort2 = sl.strings[i + 1]) then
            begin
              //innerhalb der wortgruppe nach übereinstimmung suchen
              for i3 := 0 to length(Database[i2].Folgewort)-1do
              begin
                if Database[i2].Folgewort[i3] = sl.strings[i + 2] then
                begin
              Inc(Database[i2].Anzahl[i3]);
              found := True;
              break;
                end
                else
                begin
                  //ohne übereinstimmung neuen untereintrag in wortpaar anlegen
                  t2 := length(Database[i2].Folgewort);
                  Setlength(Database[i2].Folgewort, t2 + 1);
                  Setlength(Database[i2].Anzahl, t2 + 1);
                  Database[i2].Folgewort[i3] := sl.strings[i + 2];
                  Database[i2].Anzahl[i3] := 1;
                  found := true;
                  break;
                end;
              end;
            end;
          end;
        end;
        if not found then
        begin
          //ohne worthauptgruppe neue wortpaarhauptgruppe anlegen
          t2 := length(Database);
          Setlength(Database, t2 + 1);
          Setlength(Database[i2].Folgewort, length(Database[i2].Folgewort)+ 1);
          Setlength(Database[i2].Anzahl, length(Database[i2].Folgewort)+ 1);
          Database[t2].Wort1 := sl.strings[i];
          Database[t2].Wort2 := sl.strings[i + 1];
          Database[t2].Folgewort[1] := sl.strings[i + 2];
          Database[t2].Anzahl[1] := 1;
        end;
      end;
      sl.Free;
 
      //Debugoutput
      Writeln(database[0].wort1 + database[0].wort2 + database[0].folgewort[0]); writeln(Database[0].anzahl[0]);
      Writeln(database[0].wort1 + database[0].wort2 + database[0].folgewort[1]); writeln(Database[0].anzahl[1]);
      Writeln(database[0].wort1 + database[0].wort2 + database[0].folgewort[2]); writeln(Database[0].anzahl[2]);
 
      //Baue satzvergleichsdatenbank auf
 
 
      //Berechne wahrscheinlichkeiten
    end


edit: habs denke gelöst

Antworten