Autor |
Beitrag |
OsCor
      
Beiträge: 55
Win XP, Win 7 (32)
Delphi 2007 Prof, RAD Studio XE2
|
Verfasst: Mo 30.01.12 15:20
Moderiert von Narses: Abgetrennt von [url=www.delphi-forum.de/...7#657367]hier[/url].
@zuma
Auf der Suche nach ganz was anderem habe ich diesen Thread überflogen. Dabei habe ich die mir noch unbekannten Methoden in Stringlist gesehen (Delimiter etc.). Da ich das Parsing von Strings, speziell von csv-Dateien (das ich sehr häufig brauche), bisher immer mit Pos, Copy und Delete erledigt habe (auch bei 800 000 Zeilen), hat mich der Hinweis darauf schier elektrisiert. Hast du Vergleiche bez. der Geschwindigkeit?
Oswald
P.S. Ich hoffe, dass mczero098 mir das Thread-Hijacking nicht verübelt.
|
|
Tranx
      
Beiträge: 648
Erhaltene Danke: 85
WIN 2000, WIN XP
D5 Prof
|
Verfasst: Mo 30.01.12 15:51
Vielleicht schaust Du mal hier rein:
www.delphi-treff.de/tutorials/
Da steht einiges zur Programmiersprache Delphi
_________________ Toleranz ist eine Grundvoraussetzung für das Leben.
|
|
jaenicke
      
Beiträge: 19312
Erhaltene Danke: 1747
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Mo 30.01.12 18:37
OsCor hat folgendes geschrieben : | Da ich das Parsing von Strings, speziell von csv-Dateien (das ich sehr häufig brauche), bisher immer mit Pos, Copy und Delete erledigt habe (auch bei 800 000 Zeilen), hat mich der Hinweis darauf schier elektrisiert. Hast du Vergleiche bez. der Geschwindigkeit? |
Wenn es schnell gehen soll, würde ich mit PChars arbeiten. Dann brauchst du nicht die ganzen Stringoperationen. Wenn die Daten entsprechend formatiert sind, könntest du einfach die CSV-Trennzeichen durch Nullzeichen ersetzen und Pointer auf die Zeilenbestandteile speichern. Das sollte sehr fix gehen.
|
|
zuma
      
Beiträge: 660
Erhaltene Danke: 21
Win XP, Win7, Win 8
D7 Enterprise, Delphi XE, Interbase (5 - XE)
|
Verfasst: Di 31.01.12 09:01
OsCor hat folgendes geschrieben : | @zuma
Auf der Suche nach ganz was anderem habe ich diesen Thread überflogen. Dabei habe ich die mir noch unbekannten Methoden in Stringlist gesehen (Delimiter etc.). Da ich das Parsing von Strings, speziell von csv-Dateien (das ich sehr häufig brauche), bisher immer mit Pos, Copy und Delete erledigt habe (auch bei 800 000 Zeilen), hat mich der Hinweis darauf schier elektrisiert. Hast du Vergleiche bez. der Geschwindigkeit?
Oswald
P.S. Ich hoffe, dass mczero098 mir das „Thread-Hijacking” nicht verübelt. |
Hallo Oswald,
ich nutze das fast nur so für alle meine Import-Routinen.
Genaue Zeitmessungen hab ich nicht, aber wir haben eine alte Routine, die das auch mit Stringzerlegung per copy, pos, usw. macht, und die is nix schneller, lediglich aufwändiger zu schreiben.
Schreibe aktuell gerade einen csv-Import, werde mal mit gettickcount messen, wie lange so ein import dauert, und dann hier bescheid sagen.
Aber unabhängig von der Geschwindigkeit ist die Stringlist/Delimiter-variante wesentlich bequemer zu proggen
Zuma
_________________ Ich habe nichts gegen Fremde. Aber diese Fremden sind nicht von hier! (Methusalix)
Warum sich Sorgen ums Leben machen? Keiner überlebts!
|
|
OsCor 
      
Beiträge: 55
Win XP, Win 7 (32)
Delphi 2007 Prof, RAD Studio XE2
|
Verfasst: Di 31.01.12 09:40
Auf die Zeiten bin ich gespannt.
@jaenicke
Meinst du mit „entsprechender Formatierung” feste Positionen innerhalb der Zeile? Wenn ja, dann fielen natürlich auch schon ohne Pointer 2 Arbeitsschritte weg. Da ich aber Endverwerter diverser Datenquellen bin, auf die ich nicht immer Einfluß habe, bleibt der „normale” csv-Input wohl Standard.
Aber vielleicht magst du noch erklären, wie du den Ansatz mit Pointer realisieren würdest? Ich sage es ehrlich: Wie viele andere habe ich die Arbeit damit bisher gescheut (hauptsächlich aus Angst vor schwer zu findenden Fehlern) - was nicht heißen muß, dass ich es nicht noch lerne
Oswald
|
|
jaenicke
      
Beiträge: 19312
Erhaltene Danke: 1747
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Di 31.01.12 10:04
OsCor hat folgendes geschrieben : | Meinst du mit entsprechender Formatierung feste Positionen innerhalb der Zeile? |
Nein, ich meine vor allem, ob escapte Zeichen vorkommen. Denn dann ist der String ja nicht im "Endzustand" drin, sondern muss bearbeitet werden.
Wenn man einfach nur die Positionen bestimmen muss, geht das sehr gut. Ein Beispiel kann ich erst heute Abend posten, da ich jetzt bei der Arbeit bin. Arbeiten tue ich auf diese Weise z.B. hier, nur bei dir lässt es sich noch weiter optimieren:
www.delphi-forum.de/viewtopic.php?p=567719
Mehr dazu heute Abend, da sollte ich kurz Zeit dafür haben. Als Maßstab: In dem verlinkten Programm lese ich eine 300 MiB .reg Datei in unter 5 Sekunden komplett zeichenweise in den Baum ein und parse diese. 
|
|
zuma
      
Beiträge: 660
Erhaltene Danke: 21
Win XP, Win7, Win 8
D7 Enterprise, Delphi XE, Interbase (5 - XE)
|
Verfasst: Di 31.01.12 14:28
Hallo OsCor,
kann leider beim aktuellen Import keine Zeiten geben,
da mit Gettickcount nicht messbar
Hab aktuell eine Datei mit 2 - n Werten pro Zeile (im Schnitt so 150 Werte)
die Zeile einer weiteren Stringlist als DelimitedText zuzuweisen,
die ersten 2 Werte in lokale Vars und den Rest in eine weitere Stringlist zu adden,
ergibt bei gettickcount keine Differenz, geht also zu schnell ums messen zu können.
Das Eintragen der Werte in die DB dauert da deutlich länger (ca. 0,016 Sec).
Ich warte auch mal auf Jaenicke, mal sehen, ob ich noch was dazulernen kann
Evtl. darf ich die Tage noch einem Kollegen helfen, der muss eine Datei mit jeweils 5000 Messwerten einlesen, die mit der DB abgleichen, aus den Differenzen ein Diagramm erstellen und dieses als PDF ablegen, das ganze muss unter 5 Sec pro Durchlauf passieren, da werden wir wohl etwas genauer auf die Zeiten achten müssen
Zuma
_________________ Ich habe nichts gegen Fremde. Aber diese Fremden sind nicht von hier! (Methusalix)
Warum sich Sorgen ums Leben machen? Keiner überlebts!
|
|
OsCor 
      
Beiträge: 55
Win XP, Win 7 (32)
Delphi 2007 Prof, RAD Studio XE2
|
Verfasst: Di 31.01.12 16:19
So zeitkritisch ist es bei mir nicht. Aber bei jetzigen Laufzeiten von 35 Sekunden bei einem Lesevorgang und knapp 900 000 Zeilen lohnt sich eine effektive Programmierung ganz sicher, zumal ich eigentlich auch noch Ergebnisse als Graphik darstellen wollte. Auswertung auf „Knopfdruck” stellen sich die Kollegen sicher anders vor
Oswald
|
|
jaenicke
      
Beiträge: 19312
Erhaltene Danke: 1747
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Do 02.02.12 08:30
So, nur kurz in den letzten Minuten geklöppelt:
Kleine Datei mit einer halben Million Einträgen mit je 6 Spalten, die ersten 20 Einträge des Arrays werden ausgegeben. Einlesezeit bei mir 0,1 Sekunden. Mehr dazu später, hab keine Zeit.
Einloggen, um Attachments anzusehen!
|
|
zuma
      
Beiträge: 660
Erhaltene Danke: 21
Win XP, Win7, Win 8
D7 Enterprise, Delphi XE, Interbase (5 - XE)
|
Verfasst: Do 02.02.12 10:07
Hallo Sebastian,
danke fürs hochladen,
hab zwar keine Zeit im Moment,
mir das genauer anzugucken,
bzw. mal eine meiner Routinen umzubauen
und nen (Geschwindigkeits-) Vergleich zu machen
aber die wird sich schon noch finden
Zuma
_________________ Ich habe nichts gegen Fremde. Aber diese Fremden sind nicht von hier! (Methusalix)
Warum sich Sorgen ums Leben machen? Keiner überlebts!
|
|
OsCor 
      
Beiträge: 55
Win XP, Win 7 (32)
Delphi 2007 Prof, RAD Studio XE2
|
Verfasst: Do 02.02.12 12:07
Danke, Sebastian! Ich werde auch erst heute abend daran kommen, aber bei der Aussicht auf schnelle Laufzeiten freue ich mich schon darauf.
Oswald
|
|
Horst_H
      
Beiträge: 1654
Erhaltene Danke: 244
WIN10,PuppyLinux
FreePascal,Lazarus
|
Verfasst: So 05.02.12 14:26
Hallo,
in 0.1 Sekunden 22,6 MB ist ja schon enorm schnell, schneller als meine Festplatte, also aus dem Cache heraus.
Bei mir dauerte das gecachte Einlesen in eine popelige Stringlist mit freepascal schon 0,2 Sekunden.
Insgesamt mit dem nacheinander zerlegen aller 507075 Zeilen in 1 Sekunde ( 3,2 Ghz Phenom II, mit ausgeschaltetem Cool&quite)
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62:
| program unbekannt;
uses Classes, SysUtils; var t0,t1 :TDateTime; i,k,sp: integer; sExec: AnsiString; AStringList, BStringList, CStringlist: TStringList; begin T1:= now; T0:= now; T0 := 2*T0-T1; AStringList:= TStringlist.Create;
sExec := IncludeTrailingPathDelimiter(GetCurrentDir)+'Mappe1.csv';
AStringList.loadfromfile(sExec); T1 := now; Writeln('Es sind ',AStringlist.Count,' Zeilen'); Writeln('Einlesezeit ',FormatDateTime('HH:NN:SS.ZZZ',T1-T0));
BStringList:= TStringlist.Create; BStringlist.delimiter := ';'; CStringList:= TStringlist.Create; k := 0; For i := 0 to AStringlist.Count-1 do begin BStringList.delimitedtext := AStringList[i]; CStringList.AddStrings(BStringList); sp := 0; While k < CStringlIst.count do begin CStringList.Objects[k] := TObject(sp shl 24+i); inc(k); inc(sp); end; end; T1 := now; AStringList.free; writeln(bStringList.text); BStringList.free;
IF k >= 40 then k:= 39 else k := CStringlist.count-1; For i := 0 to k do writeln(cStringlist[i],' Zeile ',Integer(CStringList.Objects[i]) AND $00FFFFFF:8,' Spalte ',Integer(CStringList.Objects[i]) shr 24:5) ; Writeln('Gesamtzeit: ',FormatDateTime('HH:NN:SS.ZZZ',T1-T0)); CStringlist.free; readln; end. |
Ausgabe
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37:
| Free Pascal Compiler version 2.6.0 [2011/12/25] for i386 .... Es sind 507075 Zeilen Einlesezeit 00:00:00.193 639506 assasad 639506 assasad 639506 assasad
132432 Zeile 0 Spalte 0 assasad Zeile 0 Spalte 1 132432 Zeile 0 Spalte 2 assasad Zeile 0 Spalte 3 132432 Zeile 0 Spalte 4 assasad Zeile 0 Spalte 5 132433 Zeile 1 Spalte 0 assasad Zeile 1 Spalte 1 132433 Zeile 1 Spalte 2 assasad Zeile 1 Spalte 3 132433 Zeile 1 Spalte 4 assasad Zeile 1 Spalte 5 132434 Zeile 2 Spalte 0 assasad Zeile 2 Spalte 1 .... 132437 Zeile 5 Spalte 0 assasad Zeile 5 Spalte 1 132437 Zeile 5 Spalte 2 assasad Zeile 5 Spalte 3 132437 Zeile 5 Spalte 4 assasad Zeile 5 Spalte 5 132438 Zeile 6 Spalte 0 assasad Zeile 6 Spalte 1 132438 Zeile 6 Spalte 2 assasad Zeile 6 Spalte 3 Gesamtzeit: 00:00:01.025 |
Ich gehe zunächst davon aus, dass das Einlesen nicht "die" Bremse ist.
Gruß Horst
Edit:
Ich habe jetzt auch alle Daten im Speicher mit Angabe von Zeile und Spalte ( maximal 255) .
Natürlich ist die Variante von jaenicke wesentlich speichersparender, aber selbst 900000 Zeilen lassen wohl meist im Hauptspeicher halten.
|
|
|