|
Antwort |
Registriert seit: 2. Nov 2003 Ort: Bei Kiel, SH 729 Beiträge Delphi 2006 Architect |
#1
Hallo X-Dragon,
ich beschreibe im Folgenden Messungen, die sich aus unserer Diskussion im Thread ASCII <-> ANSI ergaben, aber nichts mit der eigentlichen Fragegestellung zu tun haben. Ausgangspunkt dieser Messung war die Frage nach einer performanteren Funktion, die eine veränderte Kopie eines Eingabestrings zurückgibt, etwa in dieser Form:
Delphi-Quellcode:
Unter der Vorraussetzung, dass die Länge des Ergebnisstrings identisch mit der des Eingabestrings ist, sollte eine Lösung der Form
function GetModifiedString(const AnInputString: string): string;
var iChar: Integer; begin Result:= ''; for iChar:= 1 to Length(AnInputString) do case AnInputString[iChar] of ACharOne: Result:= Result+AnotherCharOne; ACharTwo: Result:= Result+AnotherCharTwo; else Result:= Result+AnInputString[iChar]; end; end;
Delphi-Quellcode:
ungleich performanter sein.
function GetModifiedString(const AnInputString: string): string;
var iChar: Integer; begin Result:= AnInputString; for iChar:= Length(AnInputString) downto 1 do case Result[iChar] of ACharOne: Result[iChar]:= AnotherCharOne; ACharTwo: Result[iChar]:= AnotherCharTwo; end; end; Die hier dargestellten Ergebnisse sollen das bestätigen. Die im Folgenden diskutierte Referenzimplementierung verwendet die von X-Dragon dargestellte Implementierung als "Originalversion" (I) im Vergleich zu einer gemäß der Zielstellung der Messung angepssten Version (II). In Anlehnung an die erwähnte Problemstellung, wird der Durchsatz der Routinen an 131072 (2^17) zufälligen Strings der festen Länge 8 getestet und ausgewertet. Diese Messung wird im Beispiel 8 mal für die jeweilige Implementierung wiederholt, um den Effekt von Einflussgrößen wie Caching, Fragmentierung, etc. zu minimieren bzw. zu erkennen.
Delphi-Quellcode:
Die Ausgabe des Programms eines beliebigen Laufs auf einem AMD Athlon 1,2 GHz unter Win2K hatte diese Gestalt:
program Project1;
{$APPTYPE CONSOLE} uses SysUtils, Windows; type TANSIToASCIIFunc = function(const AnInputString: string): string; //:Orginal implementation (I) by X-Dragon function AnsiToIBMAscii(const s: string): string; var i : Integer; begin Result:= ''; for i := 1 to Length(s) do case s[i] of #196: Result := Result + #142; // von Ä #214: Result := Result + #153; // von Ö #220: Result := Result + #154; // von Ü #228: Result := Result + #132; // von ä #246: Result := Result + #148; // von ö #252: Result := Result + #129; // von ü #223: Result := Result + #225; // von ß else Result := Result + s[i]; end; end; //:Modified implementation (II) function AnsiToIBMAsciiRefactored(const AnInput: string): string; var iChar : Integer; begin Result:= AnInput; for iChar := Length(Result) downto 1 do case Result[iChar] of #196: Result[iChar] := #142; // von Ä #214: Result[iChar] := #153; // von Ö #220: Result[iChar] := #154; // von Ü #228: Result[iChar] := #132; // von ä #246: Result[iChar] := #148; // von ö #252: Result[iChar] := #129; // von ü #223: Result[iChar] := #225; // von ß end; end; //:Tests performance of AFunc against strings of AnArray procedure DoTest(const AMessage: string; const AnArray: array of string; const AFunc: TANSIToASCIIFunc); var iRun: Integer; iString: Integer; iStartTime: Cardinal; iNeedTime: Cardinal; begin // run test eight times // might reveal problems with fragmentation for iRun:= 0 to 7 do begin // retrieve start time (in msecs) iStartTime:= GetTickCount; // call ANSI->ASCII converter for every string in AnArray for iString:= Low(AnArray) to High(AnArray) do AFunc(AnArray[iString]); // calculate needed time (in msecs iNeedTime:= GetTickCount-iStartTime; // output result Writeln(Format('%s (Run %d): %d msec (%d per sec)', [AMessage, Succ(iRun), iNeedTime, Length(AnArray)*1000 div Succ(iNeedTime)])); end; end; //:Regression test on given functions against string array procedure EnsureSameResults(const AStrings: array of string; const AFunctions: array of TANSIToASCIIFunc); var iString: Integer; iFunc: Integer; myResult: string; begin Assert( Length(AFunctions)>=1 ); // test every string in array for iString:= Low(AStrings) to High(AStrings) do begin // store result of first function in array myResult:= AFunctions[0](AStrings[iString]); // test stored result against result of every other function in array for iFunc:= Succ(Low(AFunctions)) to High(AFunctions) do if myResult<>AFunctions[iFunc](AStrings[iString]) then begin Writeln(Format('ERROR: String(%d)="%s", myResult="%s", AFunctions[%d]="%s"', [iString, AStrings[iString], myResult, iFunc, AFunctions[iFunc](AStrings[iString])])); Readln; Halt; end; end; Writeln(Format('Every function (%d) returns same result ', [Length(AFunctions)])); end; //:Creates random string with length of ALen function MakeRandomString(const ALen: Cardinal): string; var iChar: Cardinal; begin SetLength(Result, ALen); // use only "visible" chars (ASCII-Value>=Space-Value) for iChar:=1 to ALen do Result[iChar]:= Char(32+Random(224)); end; var myStrings: array[0..131071] of string; i: Integer; begin // fill array with random strings for i:= Low(myStrings) to High(myStrings) do myStrings[i]:= MakeRandomString(8); writeln(Format('Created %d random strings', [Length(myStrings)])); // test functions EnsureSameResults(myStrings, [AnsiToIBMAscii, AnsiToIBMAsciiRefactored]); // do test with original version DoTest('origin', myStrings, AnsiToIBMAscii); // do test with refactored version DoTest('refact', myStrings, AnsiToIBMAsciiRefactored); Readln; end.
Code:
Es ist zu erkennen, dass beide Varianten mit konstanter Geschwindigkeit arbeiten, also keine Probleme mit Speicherfragementierung oä auftreten (@X-Dragon: Die voreilige Äußerung zur Zunahme der Zeit bei (I) begründete sich in der Tatsache, dass bei jedem Aufruf an Result Konkateniert wurde), und (II) im Vergleich zu (I) 10 mal schneller arbeitet.
Created 131072 random strings
Every function (2) returns same result origin (Run 1): 771 msec (169782 per sec) origin (Run 2): 761 msec (172010 per sec) origin (Run 3): 761 msec (172010 per sec) origin (Run 4): 762 msec (171785 per sec) origin (Run 5): 771 msec (169782 per sec) origin (Run 6): 771 msec (169782 per sec) origin (Run 7): 771 msec (169782 per sec) origin (Run 8]: 761 msec (172010 per sec) refact (Run 1): 80 msec (1618172 per sec) refact (Run 2): 80 msec (1618172 per sec) refact (Run 3): 70 msec (1846084 per sec) refact (Run 4): 80 msec (1618172 per sec) refact (Run 5): 70 msec (1846084 per sec) refact (Run 6): 71 msec (1820444 per sec) refact (Run 7): 90 msec (1440351 per sec) refact (Run 8]: 70 msec (1846084 per sec) Eine Profiler-Analyse (inkl Debug-DCUs mit AQTime3) ergab, für die Unteraufrufe aus (I) und (II) Folgendes:
Code:
Die Tabellen zeigen in der Spalte "% Time with Children" die "verbrachte Zeit" in Unteraufrufen bzw. dem Code der Routine selbst ("body only") sowie die Anzahl der Aufrufe bei 131072 zu verarbeitenen Strings.
Routine Name | % Time w C | Hit Count
--------------+------------+---------- LStrFromChar | 50,01 | 1015812 LStrCat | 34,35 | 1048576 LStrClr | 8,85 | 262144 (body only) | 4,53 | 131072 LStrLen | 2,26 | 131072 Ergebnisse für (I) Routine Name | % Time w C | Hit Count --------------+------------+--------- (body only) | 43,18 | 131072 LStrAsg | 41,22 | 131072 UniqueStringA | 15,33 | 32764 LStrLen | 0,27 | 131072 Ergebnisse für (II) Es ist deutlich zu erkennen, dass (I) den Großteil der Zeit (>95%) mit der Verarbeitung von Strings (Alloziierung, Kopieren, etc.) statt mit der Fallunterscheidung, der eigentlichen Programmlogik, zubringt. In (II) hingegen, wird über 40% der Zeit für die Programmlogik genutzt und auch die Funktionen zur Stringverarbeitung werden maximal einmal pro Aufruf von (II) verwendet. Die Lösung (I) hingegen verwendet selbige etwa achtmal häufiger, was der Länge der zu verarbeitenen Strings entspricht. Die Testergebnisse zeigen, dass die Variante (II) bedingt durch effizientere Stringverarbeitung im Rahmen des Testszenarios etwa 10 mal schneller ist. Strings der Länge 4096 konnten diesen Quotienten auf über 26 Erhöhen. Ich hoffe, dass die Ergebnisse dieses Beitrags helfen können, Programme mit Stringverarbeitung performanter zu gestalten, ohne direkten Speicherzugriff, zB in Form von PChar oder ASM, verwenden zu müssen. [edit=sakura] Leerzeichen eingefügt Mfg, sakura[/edit]
gruß, choose
|
Zitat |
Registriert seit: 14. Jan 2003 Ort: Schortens 289 Beiträge Delphi 6 Enterprise |
#2
Wow, so eine Abhandlung hatte ich nun nicht erwartet .
Ich hatte mich jetzt in meinem Programm erstmal für die "veraltete" Methode entschieden, da sie bisher am schnellsten war:
Delphi-Quellcode:
Und nach den letzten Messungen in meinem Programm, dauert die Umwandlung von:
function ANSI2ASCII(AText:string):string;
const MaxLength = 255; var PText : PChar; begin PText:=StrAlloc(MaxLength); StrPCopy(PText,AText); {$IFDEF WIN32} CharToOEM(PText,PText); {32Bit} {$ELSE} AnsiToOEM(PText,PText); {16Bit} {$ENDIF} Result:=StrPas(PText); StrDispose(PText); end; ca. 230.000 Datensätze * 7 Felder * 12 Byte = 19.320.000 Byte ca. 1 Min 50 Sek. Deine verbesserte Version kann ich jetzt leider erst am Montag testen. Wobei ich noch nicht genau weiß wie ich das man besten mache, denn die ausgelesen Daten wandel ich jetzt immer direkt um und schreibe sie gleich in die DB. Zuvor hab ich die Daten ja zuerst komplett ausgelesen und umgewandelt und dann erst in die DB geschrieben . Und ich muss jetzt nur noch das da: http://www.delphipraxis.net/internal...ct.php?t=14593 ... in den Griff bekommen denn das unterbringen der 230.000 Datensätze an sich benötigt doch verhältnismäßig etwas mehr Zeit . |
Zitat |
Registriert seit: 2. Nov 2003 Ort: Bei Kiel, SH 729 Beiträge Delphi 2006 Architect |
#3
Hallo X-Dragon,
wenn ich Montag wieder im Bureau bin, könnte ich die Messung an Deiner zweiten Variante wiederholen (das "Test-Framework" ist ja nun fertig), sofern ich es bis dahin nicht vergessen habe
gruß, choose
|
Zitat |
Registriert seit: 2. Nov 2003 Ort: Bei Kiel, SH 729 Beiträge Delphi 2006 Architect |
#4
Wie angekündigt habe ich das Testszenario nun um die beiden Implementierungen (III)
Delphi-Quellcode:
vorgeschlagen von X-Dragon, sowie einer Lösung (IV), bei der die Delphi-Implementierung (ab Delphi3?) von Strings ausgenutzt wird, genauer die Tatsache, dass die Zuweisung myPChar:= PChar(myString)
gültig ist, weil die Pascal-typschen Dinge wie Längeninformation und Referenzzähler bei negativen Offsets liegen, sowie der Tatsache, dass die Strings null-terminiert sind und CharToOEM die Länge des Strings nicht verändert:
function AnsiToOEMStrAlloc(const AnInput: string): string;
var PText : PChar; begin PText:=StrAlloc(Succ(UsedStrLen)); try StrPCopy(PText, AnInput); CharToOEM(PText, PText); Result:= StrPas(PText); finally StrDispose(PText); end; end;
Delphi-Quellcode:
Mit 131072 Strings der Länge 8, die im Gegensatz zum vorherigen Test lediglich Zeichen des Alphabets sowie ein Leerzeichen und die ANSI-Umlaute und das ß enthalten, war bei einem beliebigen Testlauf folgendes Resultat mit (III=stralloc und IV=PChar) zu erkennen:
function AnsiToOEMPChar(const AnInput: string): string;
begin SetLength(Result, Length(AnInput)); CharToOEM(PAnsiChar(AnInput), PAnsiChar(Result)); end;
Code:
deutlicher wird der Geschwindkeitsvorsprung von (IV) jedoch bei Strings größerer Länge (hier: 512 Zeichen):
Created 131072 random strings (len: 8)
Each function (4) returns same result origin [Run 1]: 591 msec (221405 per sec) origin [Run 2]: 591 msec (221405 per sec) origin [Run 3]: 601 msec (217727 per sec) origin [Run 4]: 601 msec (217727 per sec) origin [Run 5]: 591 msec (221405 per sec) origin [Run 6]: 600 msec (218089 per sec) origin [Run 7]: 591 msec (221405 per sec) origin [Run 8]: 601 msec (217727 per sec) refact [Run 1]: 80 msec (1618172 per sec) refact [Run 2]: 70 msec (1846084 per sec) refact [Run 3]: 80 msec (1618172 per sec) refact [Run 4]: 71 msec (1820444 per sec) refact [Run 5]: 90 msec (1440351 per sec) refact [Run 6]: 80 msec (1618172 per sec) refact [Run 7]: 80 msec (1618172 per sec) refact [Run 8]: 90 msec (1440351 per sec) stralloc [Run 1]: 160 msec (814111 per sec) stralloc [Run 2]: 151 msec (862315 per sec) stralloc [Run 3]: 130 msec (1000549 per sec) stralloc [Run 4]: 140 msec (929588 per sec) stralloc [Run 5]: 130 msec (1000549 per sec) stralloc [Run 6]: 150 msec (868026 per sec) stralloc [Run 7]: 161 msec (809086 per sec) stralloc [Run 8]: 140 msec (929588 per sec) PChar [Run 1]: 50 msec (2570039 per sec) PChar [Run 2]: 40 msec (3196878 per sec) PChar [Run 3]: 50 msec (2570039 per sec) PChar [Run 4]: 40 msec (3196878 per sec) PChar [Run 5]: 50 msec (2570039 per sec) PChar [Run 6]: 40 msec (3196878 per sec) PChar [Run 7]: 50 msec (2570039 per sec) PChar [Run 8]: 40 msec (3196878 per sec)
Code:
Die Darstellung der Unteraufrufe sieht bei den beiden Varianten (III) und (IV) wie folgt aus:
Created 131072 random strings (len: 512)
Each function (4) returns same result origin [Run 1]: 33898 msec (3866 per sec) origin [Run 2]: 33899 msec (3866 per sec) origin [Run 3]: 33959 msec (3859 per sec) origin [Run 4]: 33889 msec (3867 per sec) origin [Run 5]: 34029 msec (3851 per sec) origin [Run 6]: 33898 msec (3866 per sec) origin [Run 7]: 33909 msec (3865 per sec) origin [Run 8]: 33769 msec (3881 per sec) refact [Run 1]: 1392 msec (94093 per sec) refact [Run 2]: 1372 msec (95463 per sec) refact [Run 3]: 1392 msec (94093 per sec) refact [Run 4]: 1392 msec (94093 per sec) refact [Run 5]: 1392 msec (94093 per sec) refact [Run 6]: 1392 msec (94093 per sec) refact [Run 7]: 1402 msec (93422 per sec) refact [Run 8]: 1392 msec (94093 per sec) stralloc [Run 1]: 1161 msec (112798 per sec) stralloc [Run 2]: 1172 msec (111740 per sec) stralloc [Run 3]: 1162 msec (112701 per sec) stralloc [Run 4]: 1161 msec (112798 per sec) stralloc [Run 5]: 1162 msec (112701 per sec) stralloc [Run 6]: 1152 msec (113679 per sec) stralloc [Run 7]: 1161 msec (112798 per sec) stralloc [Run 8]: 1172 msec (111740 per sec) PChar [Run 1]: 601 msec (217727 per sec) PChar [Run 2]: 591 msec (221405 per sec) PChar [Run 3]: 591 msec (221405 per sec) PChar [Run 4]: 601 msec (217727 per sec) PChar [Run 5]: 590 msec (221780 per sec) PChar [Run 6]: 601 msec (217727 per sec) PChar [Run 7]: 601 msec (217727 per sec) PChar [Run 8]: 591 msec (221405 per sec)
Code:
Die Tests und Profilerläufe sind unter ähnlichen Bedingungen wie beim letzten Posting durchgeführt worden und stellen die Variante (IV) als die performanteste Variante dar.
Routine Name | % Time w C | Hit Count
--------------+------------+---------- StrPas | 43,93 | 131072 StrAlloc | 13,32 | 131072 StrDispose | 12,34 | 131072 body only | 11,51 | 131072 CharToOem | 11,36 | 131072 StrPCopy | 7,54 | 131072 Ergebnisse für (stralloc) Routine Name | % Time w C | Hit Count --------------+------------+---------- LStrSetLength | 69,87 | 131072 CharToOem | 20,91 | 131072 body only | 6,35 | 131072 LStrLen | 2,87 | 131072 Ergebnisse für (PChar) Zur Erstellung der Ergebnisse habe ich den engehängten Quelltext unter D7 verwendet.
gruß, choose
|
Zitat |
Registriert seit: 3. Sep 2003 Ort: Westoverledingen 264 Beiträge Delphi 11 Alexandria |
#5
Hi Choose,
klasse gemachte Abhandlung mit guten Ansätzen für zukünftige Performance-Steigerung. Gruß Frank
Frank
|
Zitat |
Registriert seit: 25. Jun 2003 Ort: Thüringen 2.950 Beiträge |
#6
Teste mal folgendes:
Delphi-Quellcode:
Gruß Hagen
function AnsiToIBMAscii(const Source: String): String; var I: Integer; C: Char; D,S: PChar; begin SetLength(Result, Length(Source)); S := PChar(Source); D := PChar(Result); while true do begin C := S^; Inc(S); case C of #0: Break; #223: C := #225; // von ß #228: C := #132; // von ä #246: C := #148; // von ö #252: C := #129; // von ü #220: C := #154; // von Ü #196: C := #142; // von Ä #214: C := #153; // von Ö end; D^ := C; Inc(D); end; end; |
Zitat |
Registriert seit: 2. Nov 2003 Ort: Bei Kiel, SH 729 Beiträge Delphi 2006 Architect |
#7
Hallo Hagen,
gerne Teste auch auch ein bisschen Pointer-Arithmetik (nun immerhin Inkrementieren eines Pointers), allerdings wollte ich ursprünglich eine performante Lösung ohne ASM und Pointer finden. Der Vergleich mit dem bisherigen Favoriten (IV=PChar) und Deiner Implementierung (V=PArithm) bei dem geforderten Szenario
Code:
sowie Strings der Länge 512
Created 131072 random strings (len: 8)
Each function (5) returns same result PChar [Run 1]: 50 msec (2570039 per sec) PChar [Run 2]: 30 msec (4228129 per sec) PChar [Run 3]: 50 msec (2570039 per sec) PChar [Run 4]: 30 msec (4228129 per sec) PChar [Run 5]: 30 msec (4228129 per sec) PChar [Run 6]: 50 msec (2570039 per sec) PChar [Run 7]: 30 msec (4228129 per sec) PChar [Run 8]: 50 msec (2570039 per sec) PArithm [Run 1]: 40 msec (3196878 per sec) PArithm [Run 2]: 51 msec (2520615 per sec) PArithm [Run 3]: 50 msec (2570039 per sec) PArithm [Run 4]: 50 msec (2570039 per sec) PArithm [Run 5]: 40 msec (3196878 per sec) PArithm [Run 6]: 60 msec (2148721 per sec) PArithm [Run 7]: 40 msec (3196878 per sec) PArithm [Run 8]: 50 msec (2570039 per sec)
Code:
Die Aufrufe innerhalb der Funktion (V) gestalten sich wie folgt
Created 131072 random strings (len: 512)
Each function (5) returns same result PChar [Run 1]: 591 msec (221405 per sec) PChar [Run 2]: 681 msec (192187 per sec) PChar [Run 3]: 651 msec (201030 per sec) PChar [Run 4]: 641 msec (204161 per sec) PChar [Run 5]: 601 msec (217727 per sec) PChar [Run 6]: 631 msec (207392 per sec) PChar [Run 7]: 611 msec (214169 per sec) PChar [Run 8]: 661 msec (197993 per sec) PArithm [Run 1]: 1281 msec (102240 per sec) PArithm [Run 2]: 1252 msec (104606 per sec) PArithm [Run 3]: 1302 msec (100592 per sec) PArithm [Run 4]: 1452 msec (90207 per sec) PArithm [Run 5]: 1382 msec (94773 per sec) PArithm [Run 6]: 1612 msec (81259 per sec) PArithm [Run 7]: 1523 msec (86005 per sec) PArithm [Run 8]: 1422 msec (92109 per sec)
Code:
Anzumerken ist, dass die Lösung mithilfe der Pointer-Arithmetik zwar langsamer als Variante (IV) ist, allerdings ist sie ohne Zuhilfenahme von API-Funktionen realisiert. Die Größenordnung der Geschwindkeit liegt bei der Lösung (II), was nicht weiter verwundert, weil der Delphi-Compiler Code erzeugt, der direkt mit den Offsets arbeitet (displacement über EAX und EBX) und nur unwesentlich durch den Aufruf von UniqueString verlangsamt wird. Sollte also eine ähnliche Problemstellung vorliegen, für die keine optimierte API-Funktion vorhanden ist, scheint diese etwas schnellere Version (V) oder die leicht übersichtlichere Variante (II) die bisher beste Wahl zu sein.
Routine Name | % Time w C | Hit Count
--------------+------------+---------- body only | 54,58 | 131072 LStrSetLength | 33,41 | 131072 LStrLen | 12,01 | 131072 Ergebnisse für (PArithm) Vielleicht möchte noch jemand eine stark optimierte ASM-Version einreichen (zB Einlesen eines DWords und der Prämisse, dass es sich um null-terminierte Strings handelt), damit wir die Ergebnisse des Threads komplettieren können?
gruß, choose
|
Zitat |
Robert Marquardt
(Gast)
n/a Beiträge |
#8
Das "case" sollte rausfliegen und durch eine Tabelle ersetzt werden.
|
Zitat |
Registriert seit: 2. Nov 2003 Ort: Bei Kiel, SH 729 Beiträge Delphi 2006 Architect |
#9
Hallo Robert,
ich habe Deinen Vorschlag als pure Pascal-Lösung (VI) implementiert:
Delphi-Quellcode:
wobei ich die Tabelle wg des "Test-Frameworks" leider nicht als Parameter übergeben kann.
function AnsiToAsciiCharMapping(const AnInput: string): string;
var iChar: Integer; begin SetLength(Result, Length(AnInput)); for iChar:= Length(Result) downto 1 do Result[iChar]:= CharMap[Result[iChar]]; end; Mit einer Signatur der Form function AnsiToAsciiCharMapping(const AMap: TCharacterMap; const AnInput: string): string; wäre bei einer flexibleren Lösung im erzeugen Code demnach eine weitere Indirektion statt eines konstanten Displacements der Art
Code:
vorhanden...
mov dl, [edx+CharMap]
Die Ergebnisse des Laufes mit String der Länge 8 im Vergleich zu (IV) und (V)
Code:
der wirkliche Geschwindikeitsvorsprung des Mappings gegenüber der bisher schnellsten Pascal-Lösung (V) kommt erst bei längeren Strings (hier: 512 Zeichen) zum Vorschein:
Created 131072 random strings (len: 8)
Each function (3) returns same result PChar (IV) [Run 1]: 50 msec (2570039 per sec) PChar (IV) [Run 2]: 50 msec (2570039 per sec) PChar (IV) [Run 3]: 50 msec (2570039 per sec) PChar (IV) [Run 4]: 40 msec (3196878 per sec) PChar (IV) [Run 5]: 50 msec (2570039 per sec) PChar (IV) [Run 6]: 40 msec (3196878 per sec) PChar (IV) [Run 7]: 50 msec (2570039 per sec) PChar (IV) [Run 8]: 51 msec (2520615 per sec) PArith (V) [Run 1]: 50 msec (2570039 per sec) PArith (V) [Run 2]: 50 msec (2570039 per sec) PArith (V) [Run 3]: 60 msec (2148721 per sec) PArith (V) [Run 4]: 60 msec (2148721 per sec) PArith (V) [Run 5]: 50 msec (2570039 per sec) PArith (V) [Run 6]: 60 msec (2148721 per sec) PArith (V) [Run 7]: 60 msec (2148721 per sec) PArith (V) [Run 8]: 50 msec (2570039 per sec) CMapping (VI) [Run 1]: 50 msec (2570039 per sec) CMapping (VI) [Run 2]: 40 msec (3196878 per sec) CMapping (VI) [Run 3]: 50 msec (2570039 per sec) CMapping (VI) [Run 4]: 40 msec (3196878 per sec) CMapping (VI) [Run 5]: 61 msec (2114064 per sec) CMapping (VI) [Run 6]: 50 msec (2570039 per sec) CMapping (VI) [Run 7]: 50 msec (2570039 per sec) CMapping (VI) [Run 8]: 50 msec (2570039 per sec)
Code:
Die Ergebnisse der Unteraufrufe
Created 131072 random strings (len: 512)
Each function (3) returns same result PChar (IV) [Run 1]: 631 msec (207392 per sec) PChar (IV) [Run 2]: 630 msec (207721 per sec) PChar (IV) [Run 3]: 641 msec (204161 per sec) PChar (IV) [Run 4]: 631 msec (207392 per sec) PChar (IV) [Run 5]: 641 msec (204161 per sec) PChar (IV) [Run 6]: 641 msec (204161 per sec) PChar (IV) [Run 7]: 631 msec (207392 per sec) PChar (IV) [Run 8]: 641 msec (204161 per sec) PArith (V) [Run 1]: 1472 msec (88983 per sec) PArith (V) [Run 2]: 1472 msec (88983 per sec) PArith (V) [Run 3]: 1472 msec (88983 per sec) PArith (V) [Run 4]: 1482 msec (88383 per sec) PArith (V) [Run 5]: 1463 msec (89530 per sec) PArith (V) [Run 6]: 1482 msec (88383 per sec) PArith (V) [Run 7]: 1472 msec (88983 per sec) PArith (V) [Run 8]: 1462 msec (89591 per sec) CMapping (VI) [Run 1]: 1031 msec (127007 per sec) CMapping (VI) [Run 2]: 1032 msec (126884 per sec) CMapping (VI) [Run 3]: 1021 msec (128250 per sec) CMapping (VI) [Run 4]: 1032 msec (126884 per sec) CMapping (VI) [Run 5]: 1021 msec (128250 per sec) CMapping (VI) [Run 6]: 1022 msec (128125 per sec) CMapping (VI) [Run 7]: 1031 msec (127007 per sec) CMapping (VI) [Run 8]: 1042 msec (125668 per sec)
Code:
deuten an, dass eine Lösung ohne die String-Implementierung von Delphi (zB mit PChar bzw ASM) das Verfahren deutlich beschleuningen sollte!
Routine Name | % Time w C | Hit Count
--------------+------------+---------- UniqueStringA | 52,42 | 1048576 body only | 22,19 | 131072 LStrSetLength | 20,29 | 131072 LStrLen | 5,09 | 262144 Ergebnisse für (CMapping) Damit ist die Lösung (VI) mit einer Tabelle die bisher effizienteste bei Problemstellungen, zu denen es keine API-Funktionen gibt. Darüber hinaus offeriert sie den Charm, einer gänzlich flexiblen Lösung: Zeichenrelation selbst kann vollständig zur Laufzeit erstellt werden.
gruß, choose
|
Zitat |
Ansicht |
Linear-Darstellung |
Zur Hybrid-Darstellung wechseln |
Zur Baum-Darstellung wechseln |
ForumregelnEs ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.
BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus. Trackbacks are an
Pingbacks are an
Refbacks are aus
|
|
Nützliche Links |
Heutige Beiträge |
Sitemap |
Suchen |
Code-Library |
Wer ist online |
Alle Foren als gelesen markieren |
Gehe zu... |
LinkBack |
LinkBack URL |
About LinkBacks |