![]() |
AW: Anzahl eines Zeichens im String ermitteln
Hier schau mal selbst, das ist mit nur 50000 Zeichen/Bytes, achte auf den Ydobon Zeitwert. Katastrophal bei mir.
Diese Ergebnisse sind nicht unter optimalen Voraussetzungen entstanden da alle Kerne mit was anderem ausgelastet sind. Zitat:
|
AW: Anzahl eines Zeichens im String ermitteln
Delphi 2009 war ja die erste Version mit Unicode. Vermutlich war dort die Umsetzung von StringReplace schlicht noch nicht so gut.
|
AW: Anzahl eines Zeichens im String ermitteln
Liste der Anhänge anzeigen (Anzahl: 1)
Anhang 49520So in etwa würde neue GUI aussehen.
Wem noch mehr sinnvolle Optionen einfallen, bitte melden. Edit Ps: Ein Cancel Button ist nun vorhanden :) |
AW: Anzahl eines Zeichens im String ermitteln
Zitat:
Delphi-Quellcode:
habe ich momentan drinnen.
Windows, SysUtils;
Zitat:
|
AW: Anzahl eines Zeichens im String ermitteln
Wollt ihr den String nicht auch noch aufteilen und Multithreaded mit SSE/MMX/... oder besser noch mit CUDA/OpenCL/... beackern?
Zitat:
|
AW: Anzahl eines Zeichens im String ermitteln
Zitat:
PS: Wer viel misst misst Mist. Gerade beim Selbstbau von Assemblerzeugs sollte man auch beachten, dass CPUs sich unterschiedlich verhalten. Einige halbwegs Aktuelle planen z.B. schonmal vor und werden dann ausgebremst, wenn der Code sich anders/unvorhersehbar/abwechselnd verhält. Ich hatte mal eine Zählschleife gebaut und bremste meine CPU so aus, dass die For-In-Schleife von Delphi doppelt so schnell lief. :stupid: |
AW: Anzahl eines Zeichens im String ermitteln
Liste der Anhänge anzeigen (Anzahl: 2)
Anhang 49521 So sieht mein letzter Entwurf aus.
Vorkompiliert plus Source im Anhang. Es sind noch nicht alle Varianten enthalten, aber bitte testet mal ob das einem Benchmark gerecht wird. Abgesehen von noch fehlender Methoden brauche ich auch Hilfe bei etwas was mir gerade den Kopf verdreht.
Delphi-Quellcode:
So schaut nun ein kompletter Bench-Block aus, Hilfe brauche ich bei der Berechnung der Variable "Avg". Irgendwie mache ich da etwas falsch und komme gerade nicht auf die korrekte Lösung.
if ((Tests.ItemIndex = 0) or (Tests.ItemIndex = 1)) then
begin for Loops := 0 to Times.Value do begin QueryPerformanceCounter(Int64((@lpPerformanceCount1)^)); i := CharInString.miep(Data, Ch); QueryPerformanceCounter(Int64((@lpPerformanceCount2)^)); QueryPerformanceFrequency(Int64((@Frequency)^)); Curr := (1000000 * (lpPerformanceCount2.QuadPart - lpPerformanceCount1.QuadPart) / Frequency.QuadPart); if Loops = 0 then begin Last := Curr; Min := Curr; Max := Curr; Avg := Curr; end; if Curr < Min then Min := Curr; if Curr > Max then Max := Curr; if Curr < Last then Avg := (((Curr - Last) / 2) - Avg); if Curr > Last then Avg := (((Curr - Last) / 2) + Avg); Last := Curr; if fCancel = True then Break; end; Avg := Abs(Avg); if b = False then lstResults.Items.Add(format('%.10d',[Round(Avg)])+ ' - Statistic: [ASCII Data] ['+IntToStr(Round( Min + ((Max-Min)/2) ))+' Avg] ['+IntToStr(Round(Min))+' Min] ['+IntToStr(Round(Max))+' Max] [found ' + IntToStr(Ord(Ch)) + ' = '+IntToStr(i)+' times] @ Miep()'); if b = True then lstResults.Items.Add(format('%.10d',[Round(Avg)])+ ' - Statistic: [Binary Data] ['+IntToStr(Round( Min + ((Max-Min)/2) ))+' Avg] ['+IntToStr(Round(Min))+' Min] ['+IntToStr(Round(Max))+' Max] [found ' + IntToStr(Ord(Ch)) + ' = '+IntToStr(i)+' times] @ Miep()'); end; if fCancel = True then goto cancel; Die "Avg" Variable soll den praktischen Durchschnittswert darstellen wohingegen
Delphi-Quellcode:
den synthetischen Durchschnittswert darstellt.
['+IntToStr(Round( Min + ((Max-Min)/2) ))+' Avg]
Oder mache ich es bereits richtig? Mir dröhnt der Kopf. *Hilfe* So hier sehen nun die Ergebnisse aus: Zitat:
Ps: Da es noch nicht Threaded kann man noch nicht Canceln !!! |
AW: Anzahl eines Zeichens im String ermitteln
Zitat:
Delphi-Quellcode:
einfach durch ein
{$IFDEF CPUX86}
Delphi-Quellcode:
(Das "N" nicht vergessen)
{$IFNDEF CPUX64}
|
AW: Anzahl eines Zeichens im String ermitteln
Zitat:
Aktuell schaut deine Messung so aus:
Delphi-Quellcode:
Die Auflösung von QueryPerformanceCounter liegt zwar unter 1 Mikrosekunde, aber deine Messungen liegen zum Teil deutlich unter diesem Wert. Das bedeutet, daß die gemessene Laufzeit im Bereich oder sogar unter der Messgenauigkeit liegt, was einen relativ hohen Messfehler, schlimmstenfalls sogar vollkommen unbrauchbare Ergebnisse erwarten lässt.
QueryPerformanceCounter(Int64((@lpPerformanceCount1)^));
i := CharInString.miep(Data, Ch); QueryPerformanceCounter(Int64((@lpPerformanceCount2)^)); Diesen Messfehler kannst du sehr leicht reduzieren, wenn du die Messung über eine deutlich größere Anzahl der Aufrufe machst und dann durch diese Anzahl teilst. Die gemessene Zeit sollte also mindestens 2-3 Größenordnungen über der Messgenauigkeit liegen (das wären hier 0.01 - 0.1 ms). Aktuell versuchst du die mehrfachen Einzelmessungen zu mitteln, was dir aber nur den Mittelwert der einzelnen Fehler liefert, diesen aber nicht zwingend verkleinert (z.B. wenn er immer positiv ist). In meinem Benchmark hatte ich das schon so implementiert. Nach dem Start der Stopwatch wird die zu messende Funktion 10000x aufgerufen und dann die Gesamtzeit gemessen. Da hier nur die Rangfolge relevant ist, spare ich mir das Runterrechnen auf die mittlere Laufzeit eines einzelnen Aufrufs. Durch diese Maßnahme haben wir den obigen Messfehler auf 1/10000 verkleinert, womit er vernachlässigbar wird. Nun kann man argumentieren, daß die Messung über die Schleife ja auch einen gewissen Overhead verursacht. Zu diesem Zweck mache ich einen Kalibrierungslauf mit der Fake-Funktion, die in Relation zu den später zu messenden Funktionen vernachlässigbar kurz ist. Die bisherigen Läufe ergaben alle eine vernachlässigbare Laufzeit der Timing-Schleife. Gegebenenfalls kann man den hier ermittelten Wert dann auch von den späteren Messergebnissen abziehen. Bei den 10000 Aufrufen liegt der Fehler deutlich unter 1/1000. Übrigens: Wenn deine Delphi-Version noch keine TStopwatch kennt, es gibt eine offizielle und frei verfügbare Vorgängerversion von Allen Bauer: ![]() |
AW: Anzahl eines Zeichens im String ermitteln
Zitat:
Ansonsten::thumb: |
AW: Anzahl eines Zeichens im String ermitteln
Zitat:
Sorry, nach Uwe's Text kann ich gerade nicht daran weiterwerkeln, das wäre vergebene müh. Ich mag ja gerne Kritik annehmen aber umsetzen ohne Zusatz-Komponenten. Wie es jetzt gerade ist dachte ich eigentlich ist es okay für synthetische und praktische Wertungen. Da habe ich mir wohl was vorgemacht. Seis drum, Source ist vorhanden, macht damit was ihr wollt. Ich würde zu guter Letzt gerne noch Erfahren ob denn meine Berechnung der Avg-Variable korrekt ist oder auch gänzlich falsch? |
AW: Anzahl eines Zeichens im String ermitteln
So und jetzt eine Variante mit SIMD (SSE2, benötigt mindestens Nehalem Prozessorarchitektur von 2008). Sie ist mit Delphi 2009 kompilierbar und dürfte alle bisherigen Funktion "wegblasen".
Zitat:
Delphi-Quellcode:
function AH_CountCharAsmSIMD(const Str: String; c: Char): Cardinal;
asm {$IFNDEF CPUX64} test eax, eax jz @@Empty // wenn S = '' then gibt es nichts zu tun push ebx push esi mov esi, eax xor eax, eax // Rückgabewert auf 0 setzen // Stringlänge ermitteln //mov ecx, DWORD PTR [esi-skew].StrRec.Length mov ecx, DWORD PTR [esi-$04] shl ecx, 1 // Auf Byte-Offsets umrechnen lea esi, [esi+ecx] // ESI so umrechnen, dass ESI+ECX auf das String-Ende zeigen neg ecx cmp ecx, -8 ja @@SingleChars // DX in XMM0 als DX:DX:DX:DX:DX:DX:DX:DX verteilen movd xmm0, edx pshuflw xmm0, xmm0, 0 pshufd xmm0, xmm0, 0 // Offset so ändern, damit nicht über das String-Ende hinauslesen gelesen wird add ecx, 16 jc @@RemainingChars sub esi, 16 nop // Alignment // 8 Zeichen auf einmal verarbeiten @@Loop8WideChars: movdqu xmm1, [esi+ecx] // 16 Bytes (8 Zeichen) laden pcmpeqw xmm1, xmm0 // Vergleichen. in XMM1 steht danach für jedes gefundene Zeichen $FFFF an der WORD Position pmovmskb ebx, xmm1 // Das oberste Bit jedes Bytes in XMM1 in EBX als Bit-Maske übertragen popcnt ebx, ebx // Anzahl der Bits ermitteln (CPU muss POPCNT unterstützen, Nehalem von 2008) shr ebx, 1 // Da PMOVMSKB auf Bytes anstatt auf WORDs arbeitet, haben wir doppelt so viele Bits => div 2 add eax, ebx add ecx, 16 jz @@Leave jnc @@Loop8WideChars // Offset für den Einzelzeichen-Vergleich wiederherstellen add esi, 16 @@RemainingChars: sub ecx, 16 cmp ecx, -8 ja @@SingleChars // 4 Zeichen auf einmal verarbeiten movq xmm1, QWORD PTR [esi+ecx] // 8 Bytes (4 Zeichen) laden pcmpeqw xmm1, xmm0 // Vergleichen. In XMM1 steht danach für jedes gefundene Zeichen $FFFF an der WORD Position pmovmskb ebx, xmm1 // Das oberste Bit jedes Bytes in XMM1 in EBX als Bit-Maske übertragen movzx ebx, bl // Nur die unteren 8 Bits sind korrekt befüllt alle anderen auf 0 setzen popcnt bx, bx // Anzahl der Bits ermitteln (CPU muss POPCNT unterstützen, Nehalem von 2008) shr ebx, 1 // Da PMOVMSKB auf Bytes anstatt auf WORDs arbeitet, haben wir doppelt so viele Bits => div 2 add eax, ebx add ecx, 8 jz @@Leave nop @@SingleChars: xor ebx, ebx @@Loop: cmp WORD PTR [esi+ecx], dx sete bl add eax, ebx add ecx, 2 jnz @@Loop @@Leave: pop esi pop ebx @@Empty: {$ELSE} xor rax, rax // Rückgabewert auf 0 setzen test rcx, rcx jz @@Leave // wenn S = '' then gibt es nichts zu tun mov r8, rcx // Stringlänge ermitteln //movsxd r9, DWORD PTR [r8-skew].StrRec.Length movsxd r9, DWORD PTR [r8-$04] shl r9, 1 // Auf Byte-Offsets umrechnen lea r8, [r8+r9] // E8 so umrechnen, dass R8+R9 auf das String-Ende zeigen neg r9 cmp r9, -8 ja @@SingleChars // DX in XMM0 als DX:DX:DX:DX:DX:DX:DX:DX verteilen movd xmm0, edx pshuflw xmm0, xmm0, 0 pshufd xmm0, xmm0, 0 // Offset so ändern, damit nicht über das String-Ende hinauslesen gelesen wird add r9, 16 jc @@RemainingChars sub r8, 16 nop; nop // alignment // 8 Zeichen auf einmal verarbeiten @@Loop8WideChars: movdqu xmm1, [r8+r9] // 16 Bytes (8 Zeichen) laden pcmpeqw xmm1, xmm0 // Vergleichen. In XMM1 steht danach für jedes gefundene Zeichen $FFFF an der WORD Position pmovmskb ecx, xmm1 // Das oberste Bit jedes Bytes in XMM1 in ECX als Bit-Maske übertragen popcnt ecx, ecx // Anzahl der Bits ermitteln (CPU muss POPCNT unterstützen, Nehalem von 2008) shr ecx, 1 // Da PMOVMSKB auf Bytes anstatt auf WORDs arbeitet, haben wir doppelt so viele Bits => div 2 add eax, ecx add r9, 16 jz @@Leave jnc @@Loop8WideChars // Offset für den Einzelzeichen-Vergleich wiederherstellen add r8, 16 @@RemainingChars: sub r9, 16 cmp r9, -8 ja @@SingleChars // 4 Zeichen auf einmal verarbeiten movq xmm1, QWORD PTR [r8+r9] // 8 Bytes (4 Zeichen) laden pcmpeqw xmm1, xmm0 // Vergleichen. in XMM1 steht danach für jedes gefundene Zeichen $FFFF an der WORD Position pmovmskb ecx, xmm1 // Das oberste Bit jedes Bytes in XMM1 in ECX als Bit-Maske übertragen movzx ecx, cl // Nur die unteren 8 Bits sind korrekt befüllt alle anderen auf 0 setzen popcnt cx, cx // Anzahl der Bits ermitteln (CPU muss POPCNT unterstützen, Nehalem von 2008) shr ecx, 1 // Da PMOVMSKB auf Bytes anstatt auf WORDs arbeitet, haben wir doppelt so viele Bits => div 2 add eax, ecx add r9, 8 jz @@Leave nop // Alignment @@SingleChars: xor ecx, ecx @@Loop: cmp WORD PTR [r8+r9], dx sete cl add eax, ecx add r9, 2 jnz @@Loop @@Leave: {$ENDIF ~CPUX64} end; |
AW: Anzahl eines Zeichens im String ermitteln
Danke Andreas, mit Deinem "{$IFNDEF CPUX64}" fix funktionieren nun alle ASM Varianten, auch die von jaenicke, bei mir. Krasse Ergebnisse, mein lieber Herr Gesangsverein.
|
AW: Anzahl eines Zeichens im String ermitteln
Zitat:
avgn := Sumi:1..n(xi)/N; // xi = Wert bei Iteration i, N Anzahl Iterationen. Rekursiv ergibt sich daraus: avgn+1 := (avgn*N + xn+1)/(N+1)
Delphi-Quellcode:
Einfacher wäre aber die Berechnung der Summe innerhalb der Schleife und anschließende Division durch die Anzahl für das avg nach der Schleife.
if Loops = 0 then
begin Last := Curr; Min := Curr; Max := Curr; Avg := Curr; end else begin if Curr < Min then Min := Curr; if Curr > Max then Max := Curr; Avg := (Loops*Avg + Curr)/(Loops + 1); Last := Curr; end; |
AW: Anzahl eines Zeichens im String ermitteln
Zitat:
|
AW: Anzahl eines Zeichens im String ermitteln
Zitat:
|
AW: Anzahl eines Zeichens im String ermitteln
Zitat:
Dank Deines Links und Text bin ich nun im Bilde. edit
Delphi-Quellcode:
So habe ich es nun geregelt, sollte overhead reduzieren. Vielen Dank Uwe!
if Loops = 0 then
begin Min := Curr; Max := Curr; Avg := Curr; end else begin if Curr < Min then Min := Curr; if Curr > Max then Max := Curr; Avg := Avg + Curr; end; if fCancel = True then Break; end; // <- hier endet eine For-Schleife (Loops) Avg := Avg / Loops; |
AW: Anzahl eines Zeichens im String ermitteln
Kleine Anregungen:
Zitat:
Zitat:
Zitat:
Zitat:
Des weiteren muß ich KodeZwerg, wegen der Bemerkung über die Lösung von Ydobon recht geben, zu viele theoretische MemAllocs, welche nicht vergleichbar wären, wenn ... wird den der Code wirklich zu 100%, wie geschrieben, unter XE10.2 ausgeführt??? Weiß der Teufel, wie das zu geht. im Test selber sollte der gesuchte Char, sowohl die Größe als auch Inhalt des Strings wechseln um alle Ungereimtheiten auszuschließen. Ansonsten folgende Aufgabe in den Raum gestellt: Ich bekomme die Aufgabe die Anzahl eines Buchstaben in einem Buch zu finden. Ich soll sie von 1 bis 10000 wiederholen. Buchstabe und Buch wechseln nicht (lt. Uwes Test). Angenommen ihr währed unfehlbar und das Ergebnis steht nach Durchlauf 1 fest ... Wie oft würdet ihr den Job tatsächlich machen? Die damit verbundene Hypothese: Könnte der Compiler soweit optimiert wurden sein, solch ein Scenario zu erkennen? Mir kommt Uwes Test a bizzl so vor, als messen wir nur den einmaligen Aufruf-Stack.. Edit: @@@@jbg Einfach der Hammer !!! Aber schau mal ob dein Result initialisiert ist, wenn nix zu tun ist! |
AW: Anzahl eines Zeichens im String ermitteln
Zitat:
Alles Win32 (die Zeiten für 100000 dauern mir jetzt zu lange): Zitat:
Zitat:
|
AW: Anzahl eines Zeichens im String ermitteln
@Uwe
ist nur 'ne bescheidene Hypothese. Dennoch sind mir die Ergebnisse von Ydobon viel zu nah an allen anderen. Bist du da mit mir einig? IMO spukt es da ein wenig. Alle sollten sich je nach {$R+} minimal aneinander reihen. Die Theorie die Optimirung von StringReplace ist für mich vom Tisch... |
AW: Anzahl eines Zeichens im String ermitteln
Zitat:
Zitat:
|
AW: Anzahl eines Zeichens im String ermitteln
Zitat:
Ich habe die 64-Bit Version in meinen beiden Posts korrigiert. |
AW: Anzahl eines Zeichens im String ermitteln
Liste der Anhänge anzeigen (Anzahl: 1)
Falls jemand mag, im Anhang ist eine Version wo alles adjustable ist, so kann jeder selbst entscheiden wie vorgegangen werden soll.
Es kann nun in jedem Durchlauf neue Data generiert werden. <- Verlängert Tests, mehr overhead! Es kann nun in jedem Durchlauf nach was anderem gesucht werden (ich nahm Char(Random($FF))). Ja ich werde die KodeZwerg Methoden updaten, jetzt war funktionalität im Vordergrund. |
AW: Anzahl eines Zeichens im String ermitteln
Zitat:
|
AW: Anzahl eines Zeichens im String ermitteln
@Uwe
Gerne, was früher war muß längst nicht mehr sein... Bin da immer offen! Um etwas zu lernen, hilft es mir es zu verstehen. Schnell im Pure-Pascal ist etwas, was ich mag. Daher meine Hypothese, welche meine alleinige Annahme ist und ich auch nicht beweisen kann.. @KodeZwerg Ich kuller mal ein Auge drüber, danke! Sei so gut und check meine Anmerkungen, bitte. @jbg Super! |
AW: Anzahl eines Zeichens im String ermitteln
Zitat:
|
AW: Anzahl eines Zeichens im String ermitteln
Zitat:
Dennoch stehen die Calls(50Cycles/Call) auf StringReplace, ?WChar2UStr?, GetMem, FreeMem und 240 Zeilen StringReplace im Raum (Length ist seit D2005 inlined und macht das gleiche, wie mein NativeCode oder es in den ASM varianten zu sehen ist) und 2x Code für die Stringlänge, wogegen jede andere function ohne all dem auskommt. Ich meine man sollte da schon einen merklichen Nachteil erkennen können. Darum die Hypothese. Und die An,erkung über den Test Selber, das der String in seiner Größe und Inhalt permanent wechseln sollte. Wäre dem so(IMHO usual case), würde sich die StringReplace Variante auch auf dem neuen Compiler deutlich mehr abheben und die Nachteile erleutern (der Lerneffekt für andere Benutzer sollte ja gegeben sein, oder?). Ich bin dennoch sehr beeindruckt, wie weit der Compiler Fortschritte für Optimierungen all der Schritte inzwischen gemacht hat. Würde mir ein Chart wünschen, welches solche Effeckte je nach Compiler-Entwicklungsforschritt(alt vs. neu) mal darstellt. Gibt es ein solches? Es gäbe mit Sicherheit eine Ziehlgruppe, die solche Darstellungen eher zum Kauf/Update bewegen würden als FMX,Generics,NEXTGEN &Co. Zitat:
|
AW: Anzahl eines Zeichens im String ermitteln
Also das mit dem Replace und wie der Delphi 2009 Kompiler damit umgeht versteh ich nicht.
Zitat:
Delphi-Quellcode:
Ich mache doch theoretisch genau das selbe wie Ydobon aber ein enormer Geschwindigkeitszuwachs. (Nach wie vor auf letzten Platz)
// Ydobon = i := Length(Data) - Length(StringReplace(Data, Ch, '', [rfReplaceAll]));
function TCharInString.TestStringBuilder(const aString: string; const Ch: Char): Integer; var sb: TStringBuilder; begin sb := TStringBuilder.Create; sb.Append(aString); sb.Replace(Ch, ''); Result := Length(aString) - sb.Capacity; FreeAndNil(sb); end; Eine neue Version mit noch mehr nützlichen Optionen ist bereits fertig, auch Egons fehlende Methoden sind enthalten. Wenn ich meine StrScan() Methode korrigiere, kommt Uwes Variante bei raus also habe ich nun eine Sicherheits-CheckBox die CountCharInString(), CharInStringA() und CharCount() vom Test ausschließt. CharInStringA() weist noch einen bösen Fehler auf, Char <> AnsiChar Konvertierung schlägt sporadisch fehl, ich vermute ab Char 7F wird es knallen. So wie Uwe es gemacht hat, mit einer Werte-Kontrolle kann ich bei mir so nicht einbauen da doppelter overhead produziert werden würde (ist dem Random(Char) zu verdanken ^_^) |
AW: Anzahl eines Zeichens im String ermitteln
Zitat:
Code:
Der Result-String wird also bei jedem gefundenen Zeichen zweimal verlängert, wobei in vielen Fällen wohl ein komplettes Umkopieren von Result nötig ist. Das StringReplace ist in D2009 eben extrem unperformant und speicherhungrig implementiert, dafür aber deutlich leichter zu lesen und zu verstehen.
1. Initialisiere Result mit einem Leerstring und setze die Position auf den Anfang des Strings
2. Suche das nächste Vorkommen des Such-Patterns 3. Hänge den String vom Start bis zur Startposition des Such-Patterns bzw. Ende des Strings (wenn nicht gefunden) an den Result an 4. Brich ab, wenn das Such-Pattern nicht gefunden wurde 5. Hänge das Ersetzen-Pattern dran 6. Rücke vor bis zum Ende des Such-Patterns 7. Wiederhole ab Schritt 2 Es ist noch anzumerken, daß diese StringReplace-Optimierung erst in Delphi 10.1 Berlin eingeführt wurde. |
AW: Anzahl eines Zeichens im String ermitteln
Zitat:
Wenn Du heute mal Zeit hast würde mich ein Ergebnis Tokyo Ydobon vs TestStringBuilder() Interessieren, ob da der StringBuilder auch noch die Nase vorne hat? |
AW: Anzahl eines Zeichens im String ermitteln
Hab noch etwas gebastelt aber ist auch nicht sehr effektiv.
Delphi-Quellcode:
// versuche 4 compares pro loop abzufertigen
function TCharInString.MultiCountChar(const s: string; const c: Char): Integer; var i, ii, iii, iiii: Integer; begin Result := 0; ii := Length(s); iii := (ii div 2); iiii := iii+1; for i := 1 to (Length(s) div 2) do begin if s[i] = c then Inc(Result, 1); // suche vom Anfang in Richtung Mitte if s[ii] = c then Inc(Result, 1); // suche vom Ende in Richtung Mitte if s[iii] = c then Inc(Result, 1); // suche von Mitte in Richtung Anfang if s[iiii] = c then Inc(Result, 1); // suche von Mitte in Richtung Ende Dec(ii); Dec(iii); Inc(iiii); if i = iii then Break; end; end; |
AW: Anzahl eines Zeichens im String ermitteln
Sinnlos auf unnötig viele Vaiablen zugreifen und im Speicher kreuzundquer? Da kann dann nichtmal ein ordentliches Pageging/Caching gut arbeiten.
Eventuell werden Chars doppelt, dreifach oder gar vierfach gezählt und anstatt die Schleife gleich im richtigen Bereich laufen zu lassen noch eine zusätzliche Abbruchprüfung. Eine Schleife mit nur einer Zähler- und Ende-Variable und zugriff auf nur eine Page nach der Anderen, anstatt kreuzundquer. Oder, 4 oder 8 zusammenhängende und ausgerichtete (align) Bytes in ein Register (lokale temporäre Variable innerhalb der Schleife) einlesen und direkt im Register prüfen. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 13:16 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