Autor Beitrag
OsCor
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 55

Win XP, Win 7 (32)
Delphi 2007 Prof, RAD Studio XE2
BeitragVerfasst: Mo 30.01.12 15:20 
Moderiert von user profile iconNarses: 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 648
Erhaltene Danke: 85

WIN 2000, WIN XP
D5 Prof
BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19312
Erhaltene Danke: 1747

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Mo 30.01.12 18:37 
user profile iconOsCor hat folgendes geschrieben Zum zitierten Posting springen:
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
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 660
Erhaltene Danke: 21

Win XP, Win7, Win 8
D7 Enterprise, Delphi XE, Interbase (5 - XE)
BeitragVerfasst: Di 31.01.12 09:01 
user profile iconOsCor hat folgendes geschrieben Zum zitierten Posting springen:
@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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 55

Win XP, Win 7 (32)
Delphi 2007 Prof, RAD Studio XE2
BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19312
Erhaltene Danke: 1747

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Di 31.01.12 10:04 
user profile iconOsCor hat folgendes geschrieben Zum zitierten Posting springen:
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
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 660
Erhaltene Danke: 21

Win XP, Win7, Win 8
D7 Enterprise, Delphi XE, Interbase (5 - XE)
BeitragVerfasst: 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 55

Win XP, Win 7 (32)
Delphi 2007 Prof, RAD Studio XE2
BeitragVerfasst: 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 :roll:

Oswald
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19312
Erhaltene Danke: 1747

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 660
Erhaltene Danke: 21

Win XP, Win7, Win 8
D7 Enterprise, Delphi XE, Interbase (5 - XE)
BeitragVerfasst: 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 55

Win XP, Win 7 (32)
Delphi 2007 Prof, RAD Studio XE2
BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1654
Erhaltene Danke: 244

WIN10,PuppyLinux
FreePascal,Lazarus
BeitragVerfasst: 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)

ausblenden volle Höhe Delphi-Quelltext
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;
  
  //Alle Zeilen zerlegen
  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;  
  //Ausgabe der letzten verarbeiteten Zeile 
  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
ausblenden volle Höhe Quelltext
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.