Autor |
Beitrag |
Heiko
      
Beiträge: 3169
Erhaltene Danke: 11
|
Verfasst: Mi 21.09.05 16:25
Der Titel sagt ja eigentlich schon alles  : Wie kann man am schnellsten den String bis zum dem nächsten Zeilenumbruch auslesen? Bisher mache ich es immer so, dass ich jedes Zeichen einzelnd auf den Zeilenumbruch überprüfe. Geht das auch effektiver?
|
|
Grishnak
      
Beiträge: 221
Windows XP Home
Delphi 7 PE, Delphi 2005 PE
|
Verfasst: Mi 21.09.05 16:36
String oder Stream?
bei String: Pos()
_________________ Mach' etwas idiotensicher und irgendjemand erfindet einen besseren Idioten!
|
|
Heiko 
      
Beiträge: 3169
Erhaltene Danke: 11
|
Verfasst: Mi 21.09.05 16:40
Ne, bei einem Stream. Und mit Pos meinste, das ich nach #13#10 suchen soll  .
|
|
BenBE
      
Beiträge: 8721
Erhaltene Danke: 191
Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
|
Verfasst: Mi 21.09.05 17:30
Du kannst ein Stream Buffering verwenden:
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:
| var Len: Integer; Remaining: Integer; C: PChar; Data: String; begin Len := 0; Remaining := MS.Size - MS.Position; C := PChar(Integer(MS.Memory) + MS.Position); While (Len < Remaining) and not (C^ in [#13, #10]) Do Begin Inc(C); Inc(Len); end;
SetLength(Data, Len); MS.ReadBuffer(Data[1], Len);
If not IsBadReadPtr(C, 1) AND (C^ = #13) Then Begin Inc(C^); If not IsBadReadPtr(C, 1) AND (C^ = #10) Then MS.Seek(2, soCurrent) Else MS.Seek(1, soCurrent); end else MS.Seek(1, soCurrent); end; |
Ungetestet.
_________________ Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
|
|
Horst_H
      
Beiträge: 1654
Erhaltene Danke: 244
WIN10,PuppyLinux
FreePascal,Lazarus
|
Verfasst: Mi 21.09.05 20:11
Hallo,
einfach in eine Stringliste packen.
Das ist so verblueffend schnell.
Delphi-Quelltext 1: 2: 3: 4: 5:
| StrL :Tstringlist;
StrL.create; Strl.LoadFromStream(memstream); ... |
Gruss Horst
Moderiert von Klabautermann: Code- durch Delphi-Tags ersetzt
|
|
Heiko 
      
Beiträge: 3169
Erhaltene Danke: 11
|
Verfasst: Mi 21.09.05 20:22
Ich glaube nicht, dass es wirklich Performancevorteile bietet (ist zu einfach  ), da StringListen eigentlich nicht so für gute Performance bekannt ist  . Trotzdem thx für die Idee.
|
|
Horst_H
      
Beiträge: 1654
Erhaltene Danke: 244
WIN10,PuppyLinux
FreePascal,Lazarus
|
Verfasst: Mi 21.09.05 23:22
Hallo,
ich habe mal code-Schnipseln aus dennishomepage.gugs-.../FastCodeProject.htm wie zum Beispiel PosEX bzw.PosEy (ein char suchen) gut verwenden koennen.
CharPosEY:
fuer Athlon und P4 das schnellste:
Aus dennishomepage.gugs-...dk/CharPosEYBV12.zip
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: 63: 64: 65: 66: 67: 68: 69: 70: 71:
| function CharPosEY_JOH_IA32_2_d(const SearchCharacter : Char; const SourceString : AnsiString; Occurrence : Integer = 1; StartPos : Integer = 1): Integer; asm push ebx push edi push edx test edx, edx jz @@NotFound sub ecx, 1 jl @@NotFound cmp StartPos, 1 jl @@NotFound mov ebx, [edx-4] lea ebx, [edx+ebx-1] mov edx, StartPos add edx, [esp] sub edx, 1 jmp @@CheckFinish @@Loop: cmp al, [edx] jne @@Done1 sub ecx, 1 jc @@SetResult1 @@Done1: cmp al, [edx+1] jne @@Done2 sub ecx, 1 jnc @@Done2 cmp edx, ebx jge @@NotFound jmp @@SetResult2 @@Done2: cmp al, [edx+2] jne @@Done3 sub ecx, 1 jnc @@Done3 cmp edx, ebx jg @@NotFound jmp @@SetResult3 @@Done3: cmp al, [edx+3] jne @@Done4 sub ecx, 1 jnc @@Done4 add edx, 3 cmp edx, ebx jle @@SetResult1 @@Done4: add edx, 4 @@CheckFinish: lea edi, [edx+ecx] cmp edi, ebx jle @@Loop @@NotFound: xor eax, eax pop edx jmp @@Exit; @@SetResult3: add edx, 1 @@SetResult2: add edx, 1 @@SetResult1: pop ecx neg ecx lea eax, [edx+ecx+1] @@Exit: pop edi pop ebx end; |
Vielleicht ist das genau was Du suchst.
Gruss Horst
P.S.:
Hast Du mal Stringlisten probiert?
Moderiert von Motzi: Code- durch Delphi-Tags ersetzt
|
|
Horst_H
      
Beiträge: 1654
Erhaltene Danke: 244
WIN10,PuppyLinux
FreePascal,Lazarus
|
Verfasst: Di 27.09.05 16:44
Hallo,
ich habe es jetzt mal getestest:
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:
| procedure TForm1.Button1Click(Sender: TObject); var T0,T1,T2,T3,T4,Tf: int64; i,StartPos,EndPos : Cardinal; l : integer; pCr : pchar; begin ms:= TMemoryStream.Create; ms.Clear; If FileExists(Edit1.Text) then begin queryperformancefrequency(Tf); queryperformancecounter(T0); ms.LoadFromFile(Edit1.text); queryperformancecounter(T1); setlength(s,ms.size); ms.Position := 0; ms.ReadBuffer(s[1],ms.size); queryperformancecounter(T2); memo1.Lines.Text:=s; queryperformancecounter(T3); pCr := ms.memory; i := Cardinal(pCr); EndPos :=i+ms.Size; StartPos:= i;
repeat if pChar(i)^ = #13 then begin inc(i); if pChar(i)^ =#10 then begin l := i-Startpos-1; setlength(s,l); move(pChar(Startpos)^,S[1],l); inc(i); startPos := i; end; end; inc(i) until i >EndPos; queryperformancecounter(T4); memo1.Lines.Add(''); memo1.Lines.Add(s); s :=Format('dT1 %10.6e dt2 %10.6e dt3 %10.6e dt4 %10.6e Groesse : %10d',[ms.Size/((t1-t0)/tf),ms.Size/((t2-t1)/tf),ms.Size/((t3-t2)/tf),ms.Size/((t4-t3)/tf),ms.size]); memo1.Lines.Add(s); end; ms.Free; end; |
also grob:
Einlesen Stringstream 185 Mb/s (Cached)
in String kopieren 583 Mb/s
in Stringlist packen 3.5 Mb/s
nach und nach in String packen 120 Mb/s
Eine 2.6 Mb Datei mit 38863 Zeilen
dT1 3,60808E+008
dt2 2,40895E+008
dt3 5,93778E+006
dt4 1,40882E+008
Groesse : 2612155
Es ist schon ein gewaltiger Unterschied.
Also im Stream lassen ist das mit Abstand schnellste.
Aber stringlist ist nun mal einfacher in der Handhabung aber ueber 40 mal langsamer.
Gruss Horst
|
|
|