| Autor |
Beitrag |
Flamefire 
      
Beiträge: 1207
Erhaltene Danke: 31
Win 10
Delphi 2009 Pro, C++ (Visual Studio)
|
Verfasst: So 12.07.09 12:57
das mit dem inhaltsverzeichnis wäre noch eine idee
könnte ich machen
aber:
hab grade mal id o.g. idee implementiert:
die funktion, aus der der ausschnitt stammt, soll ein paar voranalysen machen. funktioniert aber genauso
aus zeilen mit:
"x ID1 zz
x ID2 zz
x ID2 zz"
soll jeweils die ID gespeichert werden.
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:
| function FasterCharPos(c: Char; s: PChar; l:Integer): Integer; Begin for Result := 1 to l do if s^ = c then Exit else Inc(s); Result := -1; end;
var buffer,buffer2:TDynByteArray; p,l,p2,l2,maxID,curID:Integer; curPos,curPos2:PChar; curPos2:=PChar(@buffer2[0]); Inc(curPos2,1); l2:=length(buffer2) div 2 -1; while(l2>0) do begin p2:=FasterCharPos(#9,curPos2,l2); if(p2<=0) then break; Inc(curPos2,p2); Dec(l2,p2); p2:=FasterCharPos(#9,curPos2,l2); if(p2<=0) then break; curID:=StrToIntDef(Copy(curPos2,1,p2),-1); if(curID>=0) then begin FIDTable[curID].typ:=typeMob; if(curID>maxID) then maxID:=curID; end; Inc(curPos2,p2+1); Dec(l2,p2+1); p2:=FasterCharPos(#$A,curPos2,l2); if(p2<=0) then break; Inc(curPos2,p2); Dec(l2,p2); end; |
Hab Delphi 2009 (-->Pchar=PWideChar) und die datei liegt im unicode format vor
Dummerweise: bei den knapp 10MB Daten (ca 20000 Zeilen) braucht die funktion fast eine MINUTE!
Ich brauch also dringend etwas zum optimieren. Find aber nichts mehr...
|
|
jaenicke
      
Beiträge: 19346
Erhaltene Danke: 1754
W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: So 12.07.09 13:10
Was mir auffällt:
TDynByteArray und StrToIntDef, beides liest sich komisch in dem Zusammenhang. Ein Speicherbereich, der schnell gefüllt wird, wäre vielleicht besser, und die Umwandlung in eine Zahl ist eben nicht besonders schnell.
Könntest du vielleicht ein kleines Beispielprojekt draus machen, da sollte man im Quelltext und im Profiler schnell sehen was da so lange dauert.
|
|
Flamefire 
      
Beiträge: 1207
Erhaltene Danke: 31
Win 10
Delphi 2009 Pro, C++ (Visual Studio)
|
Verfasst: So 12.07.09 13:26
ok habs grad mal mit gettickcount getract...
TDynByteArray ist ein Array of Byte (wie der name schon sagt)
darein wird die datei gelesen. geht auch kaum anders, da die datei komprimiert in einer anderen liegt
die string suchen usw sind alle verdammt schnell...
was so lange dauert ist tatsächlich StrToIntDef
Was meinst du mit "Ein Speicherbereich, der schnell gefüllt wird"
ok also muss das StrToIntDef weg oder optimiert werden.
Delphi-Quelltext 1: 2: 3: 4: 5: 6:
| TIDEntry=record typ:Byte; end; FIDTable:Array of TIDEntry; |
sinn des ganzen ist folgendes:
ich bekomme wärend des programmes häufiger IDs
die IDs sind im bereich 0-30000 (vermutlich lückenhaft, aber fast vollständig)
diese IDs stehen für verschiedene Bereiche (6 verschiedene). und ich will schnell einer ID einem bereich zuorden
also hab ich gedacht: Array[0..30000] of byte
und Bereich:=FIDTable[ID];
und fertig
Das einzige was mit einfällt ist, jetzt den string der ID zu speichern und dann jeweils nen stringvergleich zu machen.
wird aber dann um einiges langsamer als ein direkter zugriff...
|
|
jaenicke
      
Beiträge: 19346
Erhaltene Danke: 1754
W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: So 12.07.09 13:29
Flamefire hat folgendes geschrieben : | | ok habs grad mal mit gettickcount getract... |
Damit kannst du ja keine sinnvollen Ergebnisse bekommen was die einzelnen Funktionen angeht, das ist bei einzelnen Funktionen fast reiner Zufall was da raus kommt.
Geeignet sind nur Profiling-Tools oder Messungen mit QueryPerformanceCounter usw.
Flamefire hat folgendes geschrieben : | Das einzige was mit einfällt ist, jetzt den string der ID zu speichern und dann jeweils nen stringvergleich zu machen.
wird aber dann um einiges langsamer als ein direkter zugriff... |
Kommt auf die Umsetzung an. Wenn man da die Bytes vergleicht, geht das relativ schnell. Je nach Länge der IDs kann man das entsprechend optimieren.
|
|
Flamefire 
      
Beiträge: 1207
Erhaltene Danke: 31
Win 10
Delphi 2009 Pro, C++ (Visual Studio)
|
Verfasst: So 12.07.09 13:45
| Zitat: | | Damit kannst du ja keine sinnvollen Ergebnisse bekommen was die einzelnen Funktionen angeht, das ist bei einzelnen Funktionen fast reiner Zufall was da raus kommt. |
nur bedingt richtig:
wenn meine funktion 50000 ticks braucht und ich zwischenmessungen mache von verschiedenen befehlen und herausfinde, dass der strtointdef befehl fast die kompletten 50k ticks braucht, dann ist das schon sehr aussagekräftig, wie ich finde.
brauch einfach nur ne sehr einfach methode, herauszufinden, was relativ am längsten braucht, und da hat es sehr geholfen
Delphi-Quelltext 1:
| Kommt auf die Umsetzung an. Wenn man da die Bytes vergleicht, geht das relativ schnell. Je nach Länge der IDs kann man das entsprechend optimieren. |
Wie würdest du das machen?
Ich würde ein dynamisches array of record(ID:AnsiString;typ:Byte) machen und in der lesen-methode dann erst die id in nen string umwandeln dann alle einträge durchgehen und mittels comparemem vergleichen
wie kann man das noch optimieren?
Meine Variante: Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19:
| function getIDType(ID: Cardinal):Byte; var i,l:Integer; sID:AnsiString; begin if(ID<Cardinal(Length(FIDTable))) then begin sID:=AnsiString(IntToStr(ID)); l:=Length(sID); for i := 0 to Length(FIDTable) - 1 do begin with FIDTable[i] do begin if(Length(ID)<>l) then continue; if(CompareMem(@ID[1],@sID[1],l)) then begin Result:=typ; exit; end; end; end; end; Result:=typeUK;end; |
EDIT: Hab grade mal weiter getestet, da das mit dem string nicht schneller war
Die langsame methode ist Copy()!!!
Mit Delphi-Quelltext 1: 2:
| SetLength(curID,p2); Move(curPos2^,curID[1],p2*sizeOf(curID[1])); |
ist das ganze praktisch sofort durchgelaufen.
Woran liegt das denn schon wieder?
|
|
ffgorcky
      
Beiträge: 573
WIN XP/2000 & 7Prof (Familie:Win95,Win98)
|
Verfasst: So 12.07.09 15:19
Flamefire hat folgendes geschrieben : | EDIT: Hab grade mal weiter getestet, da das mit dem string nicht schneller war
Die langsame methode ist Copy()!!!
Mit Delphi-Quelltext 1: 2:
| SetLength(curID,p2); Move(curPos2^,curID[1],p2*sizeOf(curID[1])); |
ist das ganze praktisch sofort durchgelaufen.
Woran liegt das denn schon wieder? |
Das müsste doch eigentlich und für solch einen (lt. der Beitrags-Anzahl) erfahrenen, wie Dich ganz klar sein:
Durch Copy muss doch erst mal wieder neuer Arbeitsspeicher zur Verfügung gestellt werden, wärend durch Move doch nur "der Index" gewechselt wird.
Entschuldigung für diese Antwort - auch ich habe öfter einfach mal "ein Brett vor dem Kopf"...
|
|
Flamefire 
      
Beiträge: 1207
Erhaltene Danke: 31
Win 10
Delphi 2009 Pro, C++ (Visual Studio)
|
Verfasst: So 12.07.09 15:45
hmm...bin trotzdem der meinung dass copy() zu meiner lösung äquivalent ist, außer dass es noch die länge prüft und ab einer bestimmten position kopieren kann
ich lege doch auch per SetLength neuen speicher an, und kopiere dann die werte
oder hab ich move falsch verstanden?
|
|
ffgorcky
      
Beiträge: 573
WIN XP/2000 & 7Prof (Familie:Win95,Win98)
|
Verfasst: So 12.07.09 17:32
Soweit ich denke, ändert Move doch nur den Zeiger auf den Speicherplatz, lässt aber den Speicherplatzinhalt dort, wo er vorher auch war (sprich: er verschiebt nicht so viele Bits) - oder?
Da müsstest Du wahrscheinlich von anderen verlässlichere Antworten bekommen.
|
|
jaenicke
      
Beiträge: 19346
Erhaltene Danke: 1754
W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: So 12.07.09 18:17
ffgorcky hat folgendes geschrieben : | | Soweit ich denke, ändert Move doch nur den Zeiger auf den Speicherplatz, lässt aber den Speicherplatzinhalt dort, wo er vorher auch war (sprich: er verschiebt nicht so viele Bits) - oder? |
Nein, Move kopiert ebenso den Inhalt. Allerdings wird dabei keine Bereichsprüfung durchgeführt. Diese Prüfung sollte allerdings eigentlich nicht so lange dauern.
Was bei Copy passiert sind zusätzlich Stringoperationen, evtl. ist es deshalb langsamer, ich selbst arbeite da öfter auch mit SetString + CopyMemory oder so, je nach Anwendungszweck.
|
|
|