![]() |
AW: Anzahl eines Zeichens im String ermitteln
Wo zum Henker soll das sein? :shock:
Nein das hilft nicht. Was mir helfen würde wäre vllt. der Inhalt der CPU Register am Anfang meiner Funktion. Habe das Gefühl dass da wie gesagt etwas nicht so ankommt wie erwartet. |
AW: Anzahl eines Zeichens im String ermitteln
Zitat:
Delphi-Quellcode:
diese Zeile verursacht bei mir den Fehler.
mov ecx, len
|
AW: Anzahl eines Zeichens im String ermitteln
Zitat:
Wie zum Teufel kann diese Zeile einen Fehler verursachen? Zeig mir bitte den die CPU Register direkt nachdem in die Funktion gesprungen wird. Da ist irgendwas komplett faul.. |
AW: Anzahl eines Zeichens im String ermitteln
Liste der Anhänge anzeigen (Anzahl: 1)
Zitat:
|
AW: Anzahl eines Zeichens im String ermitteln
Zitat:
Hier meine Zeiten für einen Teststring mit 500000 ASCII-Zeichen, Suche nach 'X', jeweils 10000 Calls, Zeiten in Millisekunden: Zitat:
Delphi-Quellcode:
besteht, brachte erwartungsgemäß 0 ms. Die übrigen Werte schwanken bei wiederholten Aufrufen um weniger als 10%.
Result := 0
|
AW: Anzahl eines Zeichens im String ermitteln
Ja.
Und der Screenshot ist gemacht worden als das Programm auf dem "cld" Befehl (oder auf "asm") angehalten war? Weil dann versteh ich nicht was da los ist. Ich komme mir irgendwie verarscht vor. In den Registern ist absolut keine Spur von irgendeinem der Parameter die übergeben werden sollen. D.h. wenn überhaupt sind die Parameter auf dem Stack, was aber auch absolut keinen Sinn macht. Dein EIP sieht auch irgendwie seltsam aus.. Vllt. liegt das auch nur an ASLR (?). Ich weiß nicht was das Problem ist aber von dem was ich hier sehe kann ich meiner Funktion dafür keine Schuld geben wenn aus welchem Grund auch immer bei euch (dir) kompletter Müll in der Funktion ankommt. |
AW: Anzahl eines Zeichens im String ermitteln
Zitat:
Zitat:
|
AW: Anzahl eines Zeichens im String ermitteln
Noch ein kleiner:
Scanne von beiden Seiten und halbiere die Loop:
Delphi-Quellcode:
Wegen der Schwankungen empfehle ich jeden test mind 10x durchzuführen und einen avg zu bilden.
function EH_CharCount4(const S: string; C: Char): Cardinal;
var P, PEnd: PChar; begin Result := 0; P := Pointer(S); if P = nil then Exit; PEnd := P + PStrLenInt(NativeUInt(P) - SizeOf(StrLenInt))^-1; if PEnd = p //handle single char string then Inc(Result, Ord(P^ = C)) else while P < PEnd do begin if P^ = C then Inc(Result); Inc(P); if PEnd >= P then begin if PEnd^ = C then Inc(Result); Dec(PEnd); end; end; end; |
AW: Anzahl eines Zeichens im String ermitteln
Zitat:
Außerdem wird edi nirgends gerettet und wieder hergestellt. |
AW: Anzahl eines Zeichens im String ermitteln
Liste der Anhänge anzeigen (Anzahl: 1)
Zitat:
Es ist aber in der Tat so, daß es schon zwischen verschiedenen Compilaten durchaus Unterschiede geben kann, bei denen sich die Reihenfolge mancher Kandidaten vertauscht. Das ist wohl auch davon abhängig, was auf dem System sonst gerade noch so alles passiert. Es ist aber schon ein Trend zu erkennen. |
AW: Anzahl eines Zeichens im String ermitteln
Oh Mist du hast Recht. Das ist das Problem :wall:
Bei jcxz springt er je nachdem wo er gerade ist zu früh raus. :roll: :wall: Danke! Da war ich etwas blind.. Wusste nicht dass man esi/edi sichern muss. Hab grad nachgeguckt und du hast Recht. Hab die Funktion angepasst:
Delphi-Quellcode:
function CharCountAsm(AStr: PChar; AChar: Char; len: Integer): Integer;
label loop_start, loop_ende, ende; asm push edi cld mov edi, AStr mov ax, AChar mov ecx, len xor edx, edx loop_start: repnz scasw jecxz loop_ende inc edx jmp loop_start loop_ende: jnz ende inc edx ende: mov result, edx pop edi end; |
AW: Anzahl eines Zeichens im String ermitteln
Mit
![]() Die Asm Variante reiht sich bei mir so in etwa wie die AnsiStrScan() Methode ein. Bei der "von-Vorne-und-Hinten" die EgonHugeist schrieb ist kein merklicher Zugewinn spürbar, habs testhalber mit 500MB paar mal durch, das nimmt sich nichts mit Deiner vorigen Methode. Was mich total verwirrt ist allerdings das Ydobon/StringReplace Ergebnis bei Uwe, also da hat Tokyo (falls es das war bei Dir) einen gigantischen Schritt vollbracht. Wenn ich diese Variante mit einem halben Megabyte aufrufe kann ich erstmal an Briefkasten Post holen, vielleicht ist es fertig wenn ich wieder da bin. Deshalb habe ich es rauskommentiert. Mit anderen Worten bei mir hat es bei der Zeitmessung mindestens Deinen Wert * 10000 wenn nicht gar * 1000000. Kein Scherz. Ich kann ja mal mit 50MB ein Kompilat hochladen wo das auch gebencht wird, dann seht ihr was ich meine. (Kann sein das die berechnung morgen erst fertig ist) |
AW: Anzahl eines Zeichens im String ermitteln
Liste der Anhänge anzeigen (Anzahl: 1)
Zitat:
Wegen der Performance: Habe mir Uwes Test mit XE10.2-Starter compiliert und meine 2 weiteren Version hinzugefügt. Zitat:
Zitat:
kannst du das bestätigen? Mir gehen die 30% Performance-Verlust bei meiner Variante 1 ab. Wo sind sie denn hin? Spielt der Compiler Streiche? Habt ihr andere Ergebnisse? |
AW: Anzahl eines Zeichens im String ermitteln
Zum Spaß:
Delphi-Quellcode:
Results mit Uwes test:
function EH_CharCount_4(const S: string; C: Char): Cardinal;
var P, PEnd: PChar; begin Result := 0; P := Pointer(S); if P = nil then Exit; PEnd := P + PStrLenInt(NativeUInt(P) - SizeOf(StrLenInt))^-1; if PEnd = p //handle single char string then Inc(Result, Ord(P^ = C)) else while P < PEnd do begin Inc(Result, Ord(P^ = C)); Inc(P); if PEnd >= P then begin Inc(Result, Ord(PEnd^ = C)); Dec(PEnd); end; end; end; (Run 1) Zitat:
Zitat:
|
AW: Anzahl eines Zeichens im String ermitteln
Zitat:
Zitat:
|
AW: Anzahl eines Zeichens im String ermitteln
Jetzt wird's aber interessant! Hier mal die Laufzeiten für Win64 (die ASM-Funktion fällt da logischerweise raus):
Zitat:
Delphi-Quellcode:
während die normale For-Schleife nicht so stark einbricht
Result := 0;
for Ch in S do begin Inc(Result, Ord(Ch = C)); end;
Delphi-Quellcode:
Die CharCount scheint allerdings vom 64-Bit Compiler zu profitieren.
Result := 0;
for I := Low(S) to High(S) do begin Inc(Result, Ord(S[I] = C)); end; |
AW: Anzahl eines Zeichens im String ermitteln
ich weis jetzt nicht was ihr eigentlich erreichen wollt.
![]() Google spuckt zig varianten von StrScan aus sollte man die jetzt alle einem Benchmark unterwerfen? ![]() Anscheinend soll die zweite schneller sein. gruss |
AW: Anzahl eines Zeichens im String ermitteln
Zitat:
|
AW: Anzahl eines Zeichens im String ermitteln
Zitat:
Uwe ich hätte 'ne Kiste Wein gewettet, ich gewinne. Zitat: "Again what learned". Hu nicht gewettet, puhh! Ist wirklich interessant! Sei so fair und füge meine letzte version hinzu, bitte. Macht XE10.2-Starter(32-Bit) wat anders? Ich glaube es nicht.. Wenn ich über neuere CPU's so nachdenke(die alten sterben alle :-D) -> die Challange geht an dich, congrats! :thumb: Darf man fragen auf was für einer CPU/OS-Version du da reitest? Mein 5-6 Jahre alter Laptop wackelt mit 'nem i7-3610QM, 2,3GHZ, 32GB-RAM on W10 Schaut so aus, als ob ich beginnen muß den Profilern zu trauen, während ich immer Profiler war... Bei dem code, wie geschrieben denk ich nicht mal mehr nach -> thank's 4the lesson! Gruß, Michael |
AW: Anzahl eines Zeichens im String ermitteln
Liste der Anhänge anzeigen (Anzahl: 1)
Zitat:
Zitat:
Zitat:
Zitat:
Zitat:
Zitat:
Für mich habe ich die Erkenntnis mitgenommen, daß ich mit der eingebauten Funktion im StringHelper am besten zurecht komme. Die ist bei akzeptabler Performance überall und für alle Plattformen verfügbar, ohne daß ich jedesmal eine Utility-Unit einbinden muss (und irgendwie im VCS verwalten muss). Da zählen andere Kriterien mehr als ein nur marginaler Performancevorteil. Anbei noch der letzte Softwarestand. |
AW: Anzahl eines Zeichens im String ermitteln
Liste der Anhänge anzeigen (Anzahl: 1)
Danke für für den letzten Stand.
Ich denke du hast recht. Simples Ausschlusverfahren: Ich habe mal mein XE10.2-W32 Compilate (release) angehängt. Wenn deine Version immernoch die schnellste mit der EXE ist, dann ist der Compiler ausgeschlossen und da macht deine Hardware einen guten Job. Bei mir sehen die Ergebnisse (minimale Schwankungen im >5% ) ziehmlich gleich aus. YFI: Zitat:
Ich persönlich tendiere immer dazu ein set von function zu sammeln und diese Wiederzubenutzen.. |
AW: Anzahl eines Zeichens im String ermitteln
Liste der Anhänge anzeigen (Anzahl: 1)
Double Post. Hab sind noch zwei:
mit direktem Inc des Boolschen ordinals:
Delphi-Quellcode:
ohne direktem Inc des Boolschen ordinals mit if ? then
function EH_CharCount_5(const S: string; C: Char): Cardinal;
var P, PEnd: PChar; begin Result := 0; P := Pointer(S); if P = nil then Exit; PEnd := P + PStrLenInt(NativeUInt(P) - SizeOf(StrLenInt))^-8; while P < PEnd do begin //comapre 8 Chars per loop //this is a simple technic to reduce the loop. Inc(Result, Ord(P^=C)); Inc(Result, Ord((P+1)^=C)); Inc(Result, Ord((P+2)^=C)); Inc(Result, Ord((P+3)^=C)); Inc(Result, Ord((P+4)^=C)); Inc(Result, Ord((P+5)^=C)); Inc(Result, Ord((P+6)^=C)); Inc(Result, Ord((P+7)^=C)); Inc(P, 8); end; Inc(PEnd, 8); while P < PEnd do begin Inc(Result, Ord(P^=C)); Inc(P); end; end;
Delphi-Quellcode:
Dies ist die eine typische Technik um die Loops zu reduzieren. Man kann das noch weiter aufbohren für seeehhhr lange strings.
function EH_CharCount_6(const S: string; C: Char): Cardinal;
var P, PEnd: PChar; begin Result := 0; P := Pointer(S); if P = nil then Exit; PEnd := P + PStrLenInt(NativeUInt(P) - SizeOf(StrLenInt))^-8; while P < PEnd do begin //comapre 8 Chars per loop //this is a simple technic to reduce the loop. if P^ = C then Inc(Result); if (P+1)^ = C then Inc(Result); if (P+2)^ = C then Inc(Result); if (P+3)^ = C then Inc(Result); if (P+4)^ = C then Inc(Result); if (P+5)^ = C then Inc(Result); if (P+6)^ = C then Inc(Result); if (P+7)^ = C then Inc(Result); Inc(P, 8); end; Inc(PEnd, 8); while P < PEnd do begin if P^=C then Inc(Result); Inc(P); end; end; Bei mir rockt EH_CharCount_5 am schnellsten: Zitat:
|
AW: Anzahl eines Zeichens im String ermitteln
Zitat:
Zitat:
Zitat:
|
AW: Anzahl eines Zeichens im String ermitteln
Zitat:
Zitat:
|
AW: Anzahl eines Zeichens im String ermitteln
Also ich finde die ganzen Varianten höchst interessant und man erfährt dabei ein wenig, wo typische bottlenecks sitzen.:thumb:
String.CountChar kannte ich nicht, also insofern wieder was nützliches dazugelernt (hatte dafür nur eine eigene Funktion). Cool wäre auch, eine Funktion zu haben, welche nicht nur die Anzahl der Vorkommen des Chars ermittelt, sondern auch noch deren Position z.B. in einem Array zurück gibt. Das könnte auch noch an verschiedenen Stellen hilfreich sein. Eine fertige Funktion scheint es da aber nicht zu geben, oder (String.split habe ich gesehen, gibt aber ein Array der Teilstrings zurück, ich wäre aber erst mal nur an den Positionen des gesuchten Chars interessiert)? |
AW: Anzahl eines Zeichens im String ermitteln
Zitat:
Die hiesigen Ergebnisse für Win32: Zitat:
Zitat:
|
AW: Anzahl eines Zeichens im String ermitteln
Um es selber nachvollziehen zu können: Wie ist denn
PStrLenInt definiert? |
AW: Anzahl eines Zeichens im String ermitteln
Zitat:
|
AW: Anzahl eines Zeichens im String ermitteln
Zitat:
Delphi-Quellcode:
type
//zentral deklariert PStrLenInt = ^StrLenInt; StrLenInt = {$IFDEF FPC}SizeInt{$ELSE}LongInt{$ENDIF}; |
AW: Anzahl eines Zeichens im String ermitteln
OK, Danke Uwe.
|
AW: Anzahl eines Zeichens im String ermitteln
Zitat:
|
AW: Anzahl eines Zeichens im String ermitteln
@Uwe,
mir scheint der Compiler kennt die Feder das Autors und meint es gut mit ihm :stupid: Nungut, W64 kann ich dir und CodeZwerg (warum auch immer) auf deinen Pay-Compiler wohl nicht abgraben! Beim W32 scheint er nun doch auf deiner Seite fremd zugehen.. @Harry deine Anregung wäre eine weiter Challange -> neues Thema, jodoch sehr leicht. Dieses Thema hier könnte mann auch noch um eine caseinsensitive Suche aufbohren oder so.. @CodeZwerg, wie schauts mit den Benchmarks auf deiner Seite aus?? |
AW: Anzahl eines Zeichens im String ermitteln
Zitat:
|
AW: Anzahl eines Zeichens im String ermitteln
Zitat:
Alternativ eine TList<Integer> füllen und über ToArray in ein Array umwandeln. Man kann natürlich auch erstmal das Array mit Length(S) anlegen, wenn Speicher keine Rolle spielt. |
AW: Anzahl eines Zeichens im String ermitteln
Da ich eure Sourcen nicht kompilieren kann werde ich meinen Eigenen Benchmark erweitern und bald hier vorstellen.
Geplant ist eine GUI mit einstellbarer Datenmenge, Anzahl von Wiederholungen, Einzeltests<>Multitests. Eine Idee um Schwankungen auszugleichen habe ich auch schon, was haltet ihr davon? Idee: LastNano und CurrNano hält Zeitwerte des letzten und aktuellen Vorgangs, bei neuem Durchgang wird die Differenz von Last und Curr extrahiert, geteilt und der Restwert zugerechnet/abgezogen (je nach dem). Wäre das legitim um einen guten Durchschnittswert zu erhalten? Eine "AddPosArray" funktionalität für Harry werde ich bei meiner Lieblingsfunktion von Uwe integrieren. Von Egon hab ich nur zwei Varianten, ich lade mir den letzten Eurer Sourcen und nehme alles mit rein. Als Ergebnis wird die Liste als Rangfolge dann angezeigt. |
AW: Anzahl eines Zeichens im String ermitteln
Zitat:
|
AW: Anzahl eines Zeichens im String ermitteln
Die Assemblervariante scheitert unter 64-Bit doch nur an dem Unterschied edi <> rdi. Sprich so funktioniert diese unter beidem:
Delphi-Quellcode:
Unter 64-Bit sieht das Ergebnis bei mir dann so aus:
function CharCountAsm(AStr: PChar; AChar: Char; len: Integer): Integer;
label loop_start, loop_ende, ende; asm {$ifdef cpux86} push edi {$else} push rdi {$endif} cld {$ifdef cpux86} mov edi, AStr {$else} mov rdi, AStr {$endif} mov ax, AChar mov ecx, len xor edx, edx loop_start: repnz scasw jecxz loop_ende inc edx jmp loop_start loop_ende: jnz ende inc edx ende: mov result, edx {$ifdef cpux86} pop edi {$else} pop rdi {$endif} end; Zitat:
|
AW: Anzahl eines Zeichens im String ermitteln
Dann möchte ich meine schnell zusammengeschrieben Assembler-Rountine auch noch ins Rennen werfen.
Delphi-Quellcode:
function AH_CharCountAsm(const S: string; Ch: Char): Cardinal;
asm {$IFNDEF CPUX64} test eax, eax jz @@Empty // wenn S = '' dann gibt es nichts zu tun push ebx push esi mov esi, eax xor eax, eax xor ebx, ebx // Stringlänge ermitteln //mov ecx, DWORD PTR [esi-skew].StrRec.Length mov ecx, DWORD PTR [esi-$04] // ESI auf das String-Ende zeigen lassen und ECX negieren damit ESI+ECX*2 das erste Zeichen ergibt lea esi, [esi+ecx*2] neg ecx @@Loop: cmp WORD PTR [esi+ecx*2], dx sete bl add eax, ebx inc ecx jnz @@Loop pop esi pop ebx @@Empty: {$ELSE} xor rax, rax // Rückgabewert auf 0 setzen test rcx, rcx jz @@Empty // wenn S = '' dann gibt es nichts zu tun mov r8, rcx xor ecx, ecx // Stringlänge ermitteln //movsxd r9, DWORD PTR [r8-skew].StrRec.Length movsxd r9, DWORD PTR [r8-$04] // R9 auf das String-Ende zeigen lassen und R9 negieren damit R8+R9*2 das erste Zeichen ergibt lea r8, [r8+r9*2] neg r9 @@Loop: cmp WORD PTR [r8+r9*2], dx sete cl add eax, ecx inc r9 jnz @@Loop @@Empty: {$ENDIF ~CPUX64} end;
Code:
00000 Calibrate
03237 1234588 miep 05421 Ydobon 02629 marabu 03317 Missionar 03232 alzaimar 02661 Uwe Raabe StringCountChar 02629 Uwe Raabe StringCountCharFor 02144 KodeZwerg CountCharInString 07170 KodeZwerg CharInStringA 03498 Neutral General CharCountAsm 01993 Uwe Raabe CharCount 01772 Andreas Hauladen CharCountAsm ***** 02696 Egon Hugeist CharCount_1 03242 Egon Hugeist CharCount_2 02556 Egon Hugeist CharCount_Double_Sided_3 02681 Egon Hugeist CharCount_Double_Sided_4 03318 Delphi CountChar |
AW: Anzahl eines Zeichens im String ermitteln
Danke für weiteren (ASM) Methoden, werde ich mit einbauen, ich fange jetzt mal an Delphi anzukurbeln, kann sein das morgen erst fertig, ich wills diesmal Gründlich machen und nicht nur huschi-wuschi wie die initial-Version.
@Harry, sag oder PN mir Deine Lieblingsmethode für AddPosArray funktionalität. Da ich nichts Cross-Entwickle fehlt mir da die Erfahrung was klappt und was nicht. @EWeiss, ich hab das ASM aus einer CodeLib heraus gehabt, ich glaub von den Schweizern (die langsame ASM version) und ich kann mich den anderen nur anschließen, just for fun. Was mich immer noch bei all Euren Resultaten sowas von vom Hocker haut ist wie schlecht D2009 mit der Ydobon Methode performt. Wenn ich neue Version hoch habe würde ich gerne mal das Ergebnis da sehen, mit meinem D2009 Kompilat bin ich bei Werten * 100000 oder so alle anderen Ergebnisse sind relativ gleich, kommt halt viel auf Processor-Architektur und dessen Pro-MHz Leistung an (sowie eventuelle Chipsatz-Features?). |
AW: Anzahl eines Zeichens im String ermitteln
Zitat:
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 10:30 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz