Schaut gut aus! No a bizzl kürzer:
Braucht allerdings dann ca. 30% länger, weil das INC immer ausgeführt wird, auch wenn es gar nicht nötig ist. OK, wenn der String fast nur aus dem gesuchten Zeichen besteht, dann wäre das eine Option. Die Standardmethode aus dem StringHelper
S.CountChar(C)
ist da auch nicht viel schlechter (ca. 50% länger als mein letzter Ansatz und ca. 20% länger als dein Vorschlag).
Offenbar sind die Ansätze mit PChar und Inc(P) potentiell schneller als indizierte Zugriffe in For-Schleifen. Ob der erreichbare Geschwindigkeitsgewinn aber die schlechtere Lesbarkeit und Wartbarkeit (siehe die ganzen Probleme mit Assembler) rechtfertigt, ist wohl eher zweifelhaft.
Ich habe den Benchmark etwas modifiziert und rufe die einzelnen Probanden 10000x auf um lokale Schwankungen auszugleichen - natürlich außerhalb der
IDE und im Release-Mode. Messungen im Nanosekundenbereich sind einfach nicht verlässlich genug. Da der String per Zufall generiert wird, kann man verschiedene Läufe auch nicht direkt miteinander vergleichen, nur die Rangfolge innerhalb eines Laufs. Der Zeichensatz ist ja auch etwas eingeschränkt gewählt.
Interessant! Danke!
String[i] ist immer langsam. Die Schleife ist da nicht unbedingt schuld, sondern die permanente Indexierung der Speicheraddresse und die damit verbundenen RangeChecks. Durch deinen CodeStyle ak. Pointer-Math gibt es eben diese Checks erst gar nicht nicht.
Delphi-Quellcode:
function CharCount(const S: string; C: Char): Cardinal;
var
P, PEnd: PChar;
begin
Result := 0;
P := Pointer(S);
if P = nil then Exit;
{$IFNDEF FPC}
PEnd := P + PLongInt(NativeUInt(P) - SizeOf(LongInt))^;
{$ELSE}
PEnd := P + PSizeInt(NativeUInt(P) - SizeOf(SizeInt))^;
{$ENDIF}
while P < PEnd do begin
if P^ = C then
Inc(Result);
Inc(P);
end;
end;
@Himitsu,
was soll da nicht stimmen? Das TStrRec ist sowol unter Delphi64/32 bit gleich definiert. Also wo ist der Haken, wenn du es schon ansprichst?