Schnelles CompareMemory

Hier könnt Ihr gute, von Euch geschriebene Codes posten. Sie müssen auf jeden Fall funktionieren und sollten möglichst effizient, elegant und beispielhaft oder einfach nur cool sein.
Benutzeravatar
Franky
Beiträge: 1132
Registriert: 29.08.2004 16:31
Wohnort: Münsterland
Kontaktdaten:

Schnelles CompareMemory

Beitrag von Franky »

Hi Leute :D

Hab mich heute nacht mal mit CompareMemory befasst und ne neue Routine dafür geschrieben, die im Vergleich von 20063 zu 5062 arbeitet.

Zuerst mal der Code, danach mehr dazu ;-)

Code: Alles auswählen


Procedure O_CompareMemory(wert1.l,wert2.l,l.l)
;Erstmal die Werte in Eax und Ebx setzen
MOV eax,wert2
MOV ebx,wert1

;dann die länge in ECX und EDX laden
MOV ecx,l

;EDX erhält den wert von EDX%4
MOV edx,l
Or edx,-4
XOR edx,-4

;ECX wird durch 4 geteilt
SAR ecx,2

;Um ne endlosschleife zu verhindern, gucken ob ecx=0, dann direkt zum EDX-Part springen
CMP ecx,0
JE l_o_cm_middle

;Wenn ecx>0, wird immer Longweise, also 4 Byte auf einmal verglichen
O_CM_Begin:
  MOV edi,DWord[eax]
  CMP edi,DWord[ebx]
  JNE l_o_cm_unlike
  
  ADD eax,4
  ADD ebx,4  
  DEC ecx
JNZ l_o_cm_begin


o_cm_middle:

;Direkt weg, wenn net Modulo 4
CMP edx,0
JE l_o_cm_is
MOV ecx,0
;Hier werden die übrigen bis zu 3 Byte einzeln verglichen
O_CM_Begin_B:
  MOV cl,byte[eax]
  CMP cl,byte[ebx]
  JNE l_o_cm_unlike
  
  INC eax
  INC ebx  
  DEC edx
JNZ l_o_cm_begin_b
O_cm_is:
  ProcedureReturn 1
  
O_CM_Unlike:
  ProcedureReturn 0  
        
EndProcedure
Ein Beispiel

Code: Alles auswählen


;Test 1 228 Byte

text1.s="Das ist ein seehr langer text mit etwa 200 Zeichen, ok, noch nicht ganz, kann aber bald was werden, wenn ich nur lange mit dem Tippen von Buchstaben in dieses Fenster fortfahre und mir nicht einreden lasse, das mache keinen Sinn"
text2.s="Das ist ein seehr langer text mit etwa 200 Zeichen, ok, noch nicht ganz, kann aber bald was werden, wenn ich nur lange mit dem Tippen von Buchstaben in dieses Fenster fortfahre und mir nicht einreden lasse, das mache keinen Sinn"
x=GetTickCount_()
For a=1 To 100000
     l1=CompareMemory(text1,text2,228)
Next 
x2=GetTickCount_()
For a=1 To 100000
     l2=o_CompareMemory(@text1,@text2,228)
Next 


MessageRequester("Ergebnis:","1.) "+Str(x2-x)+" , "+Str(l1)+Chr(13)+"2.) "+Str(GetTickCount_()-x2)+" , "+Str(l2))     


;Test 2, 400 kb

adra=AllocateMemory(400003)
adrb=AllocateMemory(400003)

For a=0 To 400002
       PokeB(adra+a,Random(255))
Next 

CopyMemory(adra,adrb,400003)

PokeB(adra+400002,19)
x=GetTickCount_()
For a=1 To 10000
     l1=CompareMemory(adra,adrb,400003)
Next 
x2=GetTickCount_()
For a=1 To 10000
     l2=o_CompareMemory(adra,adrb,400003)
Next 


MessageRequester("Ergebnis:","1.) "+Str(x2-x)+" , "+Str(l1)+Chr(13)+"2.) "+Str(GetTickCount_()-x2)+" , "+Str(l2))     

So nun weiteres:

1.)Arbeitsweise
Anstatt Byte für Byte durch zu gehen, prüft das Programm so weit wie möglich in longs und prüft nur die letzten 3 Bytes Byteweise (is daher auch nur bei etwas größeren sachen über ich würd mal schätzen 16 Byte (kann man ja ausrechnen, wenn man die Andere Routine kennt) nützlich)

2.)Fehler
Es ist spät, ich bin net mehr ganz nüchtern (NICHT betrunken ;)) und der Tag war anstrengend, daher will ich nicht bezweifeln, etwas übersehen zu haben ;) (Hab soeben schon den ersten gefunden und bereits behoben vor dem Posten)

3.)Kopie?
Momentan schwiert hier ne Menge an Optimierungskram durch die Räume und ich kann net ausschließen, dass ich nicht der Erste war, der oben zu sehenden Quelltext verfasst hat (nicht haargenau gleich, aber vom System her). Ich versichere hiermit aber, dass dieser Quelltext allein aus meinem Hirn stammt und auch das System von mir selbst erdacht wurde.


In diesem Sinne testet ihn doch mal auf Fehlerfreiheit :)

Schönen guten Abend :D


[Edit] Hab noch vergessen euch davor zu warnen, den Debugger an zu stellen, da der meine Funktion extrem langsam macht.[/edit]
Falsch zugeordnetes Zitat des Tages: "O'zapft is" - Edward Snowden :)