Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   Delphi PosEx? Oder doch lieber Pos? - Performance! (https://www.delphipraxis.net/190021-posex-oder-doch-lieber-pos-performance.html)

dGeek 22. Aug 2016 19:01


PosEx? Oder doch lieber Pos? - Performance!
 
Ich habe heute eine sehr interessante Entdeckung gemacht. Ihr habt sie wahrscheinlich schon vor langer Zeit gemacht, ich leider erst eben.
Ich habe entdeckt, dass PosEx() viel schneller arbeitet als Pos().

1.000.000 Mal
Delphi-Quellcode:
if Pos(IrgendeinString, UndNochIrgendeinString) > 1
werden bei mir innerhalb von circa 570 Millisekunden abgearbeitet.
Dasselbe mit PosEx jedoch innerhalb von circa 140 Millisekunden.

Sollte man demnach lieber PosEx() benutzen statt Pos()?

Der schöne Günther 22. Aug 2016 19:12

AW: PosEx? Oder doch lieber Pos? - Performance!
 
Machst du in deinem Programm wirklich 1 Mio mal hintereinander Posex oder auf mehrere Jahrzehnte verteilt? Mir persönlich ist das eigentlich immer ziemlich egal ob irgendein Wartevorgang für ein "Ich klicke auf irgendwas" nun 30 oder 31 Millisekunden dauert.

Und ja, technisch gesehen ist dieser Beitrag nicht hilfreich.

dGeek 22. Aug 2016 19:14

AW: PosEx? Oder doch lieber Pos? - Performance!
 
Selbstverständlich mache ich das nicht. Aber ich fand es schon interessant, dass PosEx() um den Faktor 3 schneller ist.

Helmi 22. Aug 2016 19:15

AW: PosEx? Oder doch lieber Pos? - Performance!
 
was gibst du denn bei PosEx als Offset an?

Der schöne Günther 22. Aug 2016 19:18

AW: PosEx? Oder doch lieber Pos? - Performance!
 
Also eine Millionen mal dauert Posex bei mir 6 Millisekunden und 7 Millisekunden für "Pos".

Delphi-Quellcode:
program Project11;

{$APPTYPE CONSOLE}

{$R *.res}

uses System.SysUtils, System.AnsiStrings, System.Diagnostics;

const
 s1 = 'Hallo Welt';
 s2 = 'lo';

 count = 1E6;

//{$Define Posex}

var
   times: Integer;
   result: Integer;
   stopWatch: TStopwatch;
begin
   times := 0;
   stopWatch := TStopwatch.StartNew();
   repeat
      {$If Defined(Posex)}
         result := System.AnsiStrings.PosEx(s2, s1);
      {$Else}
         result := System.Pos(s2, s1);
      {$EndIf}
      Inc(times);
   until (times = count);
   stopWatch.Stop();

   Writeln( stopWatch.ElapsedMilliseconds );
   readln;
end.

Wenn du in die Implementation schaust wirst du sehen dass PosEx nichts anderes tut als Pos aufzurufen. PosEx hat aber noch eine "inline"-Direktive. Ich kann kein Assembler lesen, könnte mir aber vorstellen dass der Compiler dann das komplette "Pos" inlined sodass er sich einen Sprung spart. Könnte das mal jemand prüfen?

dGeek 22. Aug 2016 19:39

AW: PosEx? Oder doch lieber Pos? - Performance!
 
Zitat:

Zitat von Der schöne Günther (Beitrag 1345430)
Also eine Millionen mal dauert Posex bei mir 6 Millisekunden und 7 Millisekunden für "Pos".


- Wir haben nicht dieselbe Delphi-Version
- Wir haben nicht denselben Computer

:lol:

p80286 22. Aug 2016 23:27

AW: PosEx? Oder doch lieber Pos? - Performance!
 
Zitat:

Zitat von dGeek (Beitrag 1345432)
Zitat:

Zitat von Der schöne Günther (Beitrag 1345430)
Also eine Millionen mal dauert Posex bei mir 6 Millisekunden und 7 Millisekunden für "Pos".


- Wir haben nicht dieselbe Delphi-Version
- Wir haben nicht denselben Computer

:lol:

Welche Delphi-Version hast Du denn?

Gruß
K-H

dGeek 22. Aug 2016 23:36

AW: PosEx? Oder doch lieber Pos? - Performance!
 
XE2 benutze ich.

Zacherl 23. Aug 2016 01:19

AW: PosEx? Oder doch lieber Pos? - Performance!
 
In den neuen Delphi Versionen scheint
Delphi-Quellcode:
PosEx
nur noch ein Alias für
Delphi-Quellcode:
Pos
zu sein. Früher hatte
Delphi-Quellcode:
Pos
noch nicht den optionalen
Delphi-Quellcode:
Offset
Parameter, deshalb brauchte man eine seperate
Delphi-Quellcode:
PosEx
Funktion.

Stevie 23. Aug 2016 07:40

AW: PosEx? Oder doch lieber Pos? - Performance!
 
Ich hab mal dem Code von Günther in XE und Berlin getestet und muss sagen, in XE (und vermutlich dann auch XE2) schien Pos enorm langsam zu sein und nicht etwa PosEx schneller (im Vergleich zu den Ergebnissen in Berlin)

P.S. Ich hab natürlich die Unicode Version von PosEx aus StrUtils verwendet und nicht die AnsiString Version - wir wollen ja nicht Äpfel und Birnen vergleichen, gell? :stupid:

dGeek 23. Aug 2016 10:07

AW: PosEx? Oder doch lieber Pos? - Performance!
 
Zitat:

Zitat von Stevie (Beitrag 1345453)
in XE schien Pos enorm langsam zu sein und nicht etwa PosEx schneller

Also entweder bin ich müde, oder ich beherrsche die deutsche Sprache nicht. Ist das hier nicht doppelt gemoppelt?
Du sagst, Pos scheint enorm langsam zu sein, und dass PosEx nicht schneller ist. Was ist denn nun schneller gewesen bei deinem Test :-D

Stevie 23. Aug 2016 10:35

AW: PosEx? Oder doch lieber Pos? - Performance!
 
Zitat:

Zitat von dGeek (Beitrag 1345458)
Zitat:

Zitat von Stevie (Beitrag 1345453)
in XE schien Pos enorm langsam zu sein und nicht etwa PosEx schneller

Also entweder bin ich müde, oder ich beherrsche die deutsche Sprache nicht. Ist das hier nicht doppelt gemoppelt?
Du sagst, Pos scheint enorm langsam zu sein, und dass PosEx nicht schneller ist. Was ist denn nun schneller gewesen bei deinem Test :-D

Ich wollte damit deine Aussage
Zitat:

Zitat von dGeek (Beitrag 1345425)
Ich habe entdeckt, dass PosEx() viel schneller arbeitet als Pos().

in Relation zu den neueren Delphi Versionen stellen - insofern: Pos (in XE) arbeitet viel langsamer als PosEx (was genauso schnell arbeitet wie Pos in neueren Versionen).

In Spring haben wir übrigens folgenden Code:
Delphi-Quellcode:
{$IFNDEF DELPHIXE3_UP}
function Pos(const SubStr, Str: UnicodeString; Offset: Integer): Integer;
asm
  jmp PosEx
end;
{$ENDIF}
:mrgreen:

dGeek 23. Aug 2016 10:39

AW: PosEx? Oder doch lieber Pos? - Performance!
 
Ok interessant.

Zur Frage, welchen offSet ich bei PosEx verwenden würde: ich benutze gar keinen. Ich gebe keinen an, also gilt 1.

p80286 23. Aug 2016 11:43

AW: PosEx? Oder doch lieber Pos? - Performance!
 
Ich habe Günthers Code mit kleinen Abweichungen (TStopwatch ist unbekannt)
durch D2006 und D7 gejagt


D2006 pos: 0,024 posex:0,024 s

D7 pos:0,152 posex 0,147 s

und hier der code:
Delphi-Quellcode:
program Project2;

{$APPTYPE CONSOLE}

{$R *.res}

uses SysUtils
 ,strutils
 ;

const
  s1 = 'Hallo Welt';
  s2 = 'lo';

  count = 2E6;

//{$Define Posex}

var
    times: Integer;
    result: Integer;
    sz,ez : tdatetime;
begin
    times := 0;
    sz:=now;
    repeat
       {$If Defined(Posex)}
          result := PosEx(s2, s1);
       {$Else}
          result := System.Pos(s2, s1);
       {$IFEnd}
       Inc(times);
    until (times = count);
    ez:=now;

    Writeln(formatdatetime('HH:MM:SS,zz', ez-sz) );
    readln;
end.
Packt man noch 40 Leerzeichen an den Anfang von S1, dann ist das Verhältnis 0,201/0,198.
Es scheint wohl wieder zu gelten: "wer misst, misst Mist"


Gruß
K-H

Stevie 23. Aug 2016 12:00

AW: PosEx? Oder doch lieber Pos? - Performance!
 
Beides Pre-Unicode Versionen, somit: Äpfel <> Birnen

Außerdem ist mit Now messen auch Tinnef.

p80286 23. Aug 2016 12:26

AW: PosEx? Oder doch lieber Pos? - Performance!
 
In beiden Fällen werden Ansis verglichen, das sind Äpfel oder Birnen aus dem gleichen Korb.
Die Ausgangsfrage war gibt es einen Unterschied zwischen pos und posex, was implizit "beim gleichen Compiler beinhaltet"?
Und im Rahmen der Meßgenauigkeit kann ich Dir sagen für D2006 und D7 gilt nein.

Gruß
K-H

himitsu 23. Aug 2016 14:26

AW: PosEx? Oder doch lieber Pos? - Performance!
 
Also "früher" gab es im Delphi kein PoSex, darum brauchte man eine eigene/fremde Implementation. (bis um Delphi 6/7 rum, irgendwann)
Aber spater war die Implementation von PosEx eigentlich fast identisch mit Pos... nur noch weitere Parameter, dessen Bereichsprüfung und dann ein anderer einstieg in die Suchschleife (loop).

Also Eigentlich sollte das PosEx einen "Hauch" von wenigen CPU-Zyklen langsamer sein.


Dann hatte man das FastCode-Projekt teilweise in Delphi integriert und k.A. wie es dann war.

Und jetzt klingt es so, als wenn man Pos durch PosEx ersetzt hat, was ja im Prinzip auch praktisch keinen Unterschied macht, wenn beides "gleich" implementiert war.

Der schöne Günther 23. Aug 2016 15:32

AW: PosEx? Oder doch lieber Pos? - Performance!
 
Ich liebe es wie sich hier bei dieser Routine auf einmal alle so viel Mühe geben die Groß/Kleinschreibung zu beachten :mrgreen:

p80286 23. Aug 2016 15:40

AW: PosEx? Oder doch lieber Pos? - Performance!
 
Zitat:

Zitat von Der schöne Günther (Beitrag 1345525)
Ich liebe es wie sich hier bei dieser Routine auf einmal alle so viel Mühe geben die Groß/Kleinschreibung zu beachten :mrgreen:

Das verstehe ich aber nicht :stupid:

Gruß
K-H

P.S.
Laut den Sourcen ist das PosEx in D7 aus dem FastCode-Projekt.

Zacherl 23. Aug 2016 17:00

AW: PosEx? Oder doch lieber Pos? - Performance!
 
Zitat:

Zitat von Der schöne Günther (Beitrag 1345525)
Ich liebe es wie sich hier bei dieser Routine auf einmal alle so viel Mühe geben die Groß/Kleinschreibung zu beachten :mrgreen:

Empfiehlt sich auch keinesfalls nach dieser Routine zu Googlen :-D

himitsu 23. Aug 2016 17:21

AW: PosEx? Oder doch lieber Pos? - Performance!
 
Wobei Google inzwischen gelernt hat und Minderheiten entsprechend verlinkt.
Bei Google suchendelphi posex

Kann aber auch daran liegen, daß Google inzwischen die "bösen" erotischen Webseiten weiter unten einsortiert. :stupid:

Der schöne Günther 23. Aug 2016 17:45

AW: PosEx? Oder doch lieber Pos? - Performance!
 
Wow, selbst die Bilder- und Videosuche ist entsprechend ... harmlos.

Pixel 23. Aug 2016 22:39

AW: PosEx? Oder doch lieber Pos? - Performance!
 
..........nvm

Pixel 24. Aug 2016 20:12

AW: PosEx? Oder doch lieber Pos? - Performance!
 
Liste der Anhänge anzeigen (Anzahl: 3)
Also ich bin kein ASM-Experte aber hab mir das ganze mal im Debugger angeschaut.

Bilder sind im Anhang.

Bei dem Bild "pos" sieht man den kompletten ASM-Code der pos-funktion :stupid:

Die Stringsuche beginnt bei Adresse 00402FE8 "REPNE SCAN BYTE PTR..."
Der ASM-Befehl sucht quasi solange nach einem String bis ECX 0 ist.

Bei Bild "posex_main" fällt erstmal auf dass die Funktion anders anfängt. Von der Stringsuchschleife von pos() sieht man erstmal nichts. Aber: z.B. gibt es bei PosEx() ja den 3. Parameter "Offset" der default auf 1 gesetzt ist. Das sieht man auf dem Bild schön bei Adresse 00407CB1 "CMP ECX,1" und "JNZ SHRT findPosi.00407CC1".

Wenn man das Offset unberührt lässt (also bei default 1) dann wird der jump JNZ - "jump if not zero" auch nicht genommen und wir landen bei Adresse 00407CBA "CALL findPosi.0040398C". Wenn man dem folgt landet man bei Bild "posex2" und jetzt erkennt man, dass wir dort dann wieder bei der Funktion pos() sind.

Also tl;dr: posEx() hat einen jump, ein CMP und ein JNZ mehr als pos() und ist somit langsamer :stupid:. posEx() kann allerdings schneller sein, wenn man das Offset setzt. Ach und: Das ganze hab ich aus Delphi 7 :stupid: :stupid: :stupid:

Edit:// Sorry ich wollte eigtl. meinen Beitrag oben editieren.


Alle Zeitangaben in WEZ +1. Es ist jetzt 08:21 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 by Thomas Breitkreuz