Page 1 of 2

We have a Mid replacement. Any thoughts on FindString ?

Posted: Sun Oct 22, 2006 11:21 pm
by yrret
I was really impressed with the speed gain with the FMid2 (Mid replacement) program. I found it consistently 10 time faster
then when using Mid. I was wondering with the expertise out there, if any one ever thought about, or think it's possible to improve the
FindString(String$, StringToFind$, StartPosition) speed?
That is one command I use alot, and it does slow the running program down when you use it alot.

Posted: Mon Oct 23, 2006 8:49 am
by jqn
And StringField(String$, Index, Delimiter$) ?
And ReplaceString(String$, StringToFind$, StringToReplace$ [, Mode [, StartPosition]]) ?

Both commands are also used alot.

Posted: Mon Oct 23, 2006 11:16 am
by wilbert
The fastest way would be to use asm with sse functions.

Using C functions already makes a significant difference.
Turn off debugging for a fair comparisson.

Code: Select all

Global hMSVCRT.l = GetModuleHandle_("msvcrt.dll")
Global fStrStr.l = GetProcAddress_(hMSVCRT, "strstr")
Global fStrLen.l = GetProcAddress_(hMSVCRT, "strlen")

Procedure.l FindString2_(*String.l, *StringToFind.l, StartPosition.l)
 If StartPosition <= CallCFunctionFast(fStrLen, *String)
  If StartPosition < 2
   StartPosition = 0
  Else 
   StartPosition - 1
  EndIf
  Protected StrPos.l = CallCFunctionFast(fStrStr, *String + StartPosition, *StringToFind)
  If StrPos
   StrPos + 1 - *String
  EndIf
  ProcedureReturn StrPos
 Else
  ProcedureReturn 0
 EndIf
EndProcedure

Macro FindString2(String, StringToFind, StartPosition)
 FindString2_(@String, @StringToFind, StartPosition)
EndMacro

#Tries = 10000000

time = GetTickCount_()
For I = 0 To #Tries
  p.l = FindString("The quick brown fox jumped over the lazy dog","lazy",7)
Next
MessageRequester("", Str(GetTickCount_()-time))

time = GetTickCount_()
For I = 0 To #Tries
  p.l = FindString2("The quick brown fox jumped over the lazy dog","lazy",7)
Next
MessageRequester("", Str(GetTickCount_()-time))

Posted: Mon Oct 23, 2006 11:51 am
by KarLKoX
Fixed code :

Code: Select all

Global hMSVCRT.l = LoadLibrary_("msvcrt.dll")
Global fStrStr.l = GetProcAddress_(hMSVCRT, "strstr")
Global fStrLen.l = GetProcAddress_(hMSVCRT, "strlen")

Procedure.l FindString2_(*String.l, *StringToFind.l, StartPosition.l)
 If StartPosition <= CallCFunctionFast(fStrLen, *String)
  If StartPosition < 2
   StartPosition = 0
  Else
   StartPosition - 1
  EndIf
  Protected StrPos.l = CallCFunctionFast(fStrStr, *String + StartPosition, *StringToFind)
  If StrPos
   StrPos + 1 - *String
  EndIf
  ProcedureReturn StrPos
 Else
  ProcedureReturn 0
 EndIf
EndProcedure

Macro FindString2(String, StringToFind, StartPosition)
 FindString2_(@String, @StringToFind, StartPosition)
EndMacro

#Tries = 10000000

time = GetTickCount_()
For I = 0 To #Tries
  p.l = FindString("The quick brown fox jumped over the lazy dog","lazy",7)
Next
first = GetTickCount_()-time


time = GetTickCount_()
For I = 0 To #Tries
  p.l = FindString2("The quick brown fox jumped over the lazy dog","lazy",7)
Next
second = GetTickCount_()-time
MessageRequester("", "PureBasic : " + Str(first) + Chr(13) + "MSVCRT : " + Str(second) )
Bench result :

PB ~ 1906
MSCVRT ~ 1140

Posted: Mon Oct 23, 2006 12:03 pm
by netmaestro
Still crashing here..

Posted: Mon Oct 23, 2006 12:55 pm
by wilbert
It doens't crash on my computer so it's hard for me to fix.

Maybe it'll help to use prototypes. I haven't used those so far since I don't know exactly how to use them.

Posted: Mon Oct 23, 2006 12:59 pm
by freak
Using prototypes is a tiny bit faster than Call(C)FunctionFast.

Posted: Mon Oct 23, 2006 1:06 pm
by traumatic
just for the sake of completeness...

Code: Select all

Global hMSVCRT.l = LoadLibrary_("msvcrt.dll")
Global fStrStr.l = GetProcAddress_(hMSVCRT, "strstr")
Global fStrLen.l = GetProcAddress_(hMSVCRT, "strlen")

PrototypeC strstr(a,b) : PrototypeC strlen(a)

Global strstr.strstr = GetProcAddress_(hMSVCRT, "strstr")
Global strlen.strlen = GetProcAddress_(hMSVCRT, "strlen")


Procedure.l FindString2_(*String.l, *StringToFind.l, StartPosition.l)
 If StartPosition <= CallCFunctionFast(fStrLen, *String)
  If StartPosition < 2
   StartPosition = 0
  Else
   StartPosition - 1
  EndIf
  Protected StrPos.l = CallCFunctionFast(fStrStr, *String + StartPosition, *StringToFind)
  If StrPos
   StrPos + 1 - *String
  EndIf
  ProcedureReturn StrPos
 Else
  ProcedureReturn 0
 EndIf
EndProcedure

Procedure.l FindString3_(*String.l, *StringToFind.l, StartPosition.l)
 If StartPosition <= Strlen(*String)
  If StartPosition < 2
   StartPosition = 0
  Else
   StartPosition - 1
  EndIf
  Protected StrPos.l = Strstr(*String + StartPosition, *StringToFind)
  If StrPos
   StrPos + 1 - *String
  EndIf
  ProcedureReturn StrPos
 Else
  ProcedureReturn 0
 EndIf
EndProcedure

Macro FindString2(String, StringToFind, StartPosition)
 FindString2_(@String, @StringToFind, StartPosition)
EndMacro

Macro FindString3(String, StringToFind, StartPosition)
 FindString3_(@String, @StringToFind, StartPosition)
EndMacro

#Tries = 10000000

time = GetTickCount_()
For I = 0 To #Tries
  p.l = FindString("The quick brown fox jumped over the lazy dog","lazy",7)
Next
first = GetTickCount_()-time


time = GetTickCount_()
For I = 0 To #Tries
  p.l = FindString2("The quick brown fox jumped over the lazy dog","lazy",7)
Next
second = GetTickCount_()-time

time = GetTickCount_()
For I = 0 To #Tries
  p.l = FindString3("The quick brown fox jumped over the lazy dog","lazy",7)
Next
third = GetTickCount_()-time

MessageRequester("", "PureBasic : " + Str(first) + Chr(13) + "MSVCRT : " + Str(second)  + Chr(13) + "MSVCRT / Proto : " + Str(third) ) 

Posted: Mon Oct 23, 2006 1:48 pm
by wilbert
Thanks Traumatic !
That helps :D

The prototype way is not only faster but also the code looks cleaner.

Posted: Mon Oct 23, 2006 2:48 pm
by netmaestro
@Traumatic,

That works here, no crashing. Debugger off is showing MSVCRT around half the proctime of native PB with proto, 60% without. Thanks for posting.

Posted: Tue Oct 24, 2006 3:36 am
by yrret
Thank you very much Traumatic !

That will really help others speed up programs
that need to use that code alot like I do. :D

Posted: Tue Oct 24, 2006 11:50 am
by SoulReaper
Wow thats Great :)

on xp1800 cpu

Pure Basic : 3515 <--- Winner :)
MSVCRT : 11375
MSVCRT Proto : 11657

@Traumatic
Thankyou for this Excellent Work...
I wonder where Microsoft went wrong :lol:

I love the speed of Pure Basic :) :twisted:

Posted: Tue Oct 24, 2006 12:16 pm
by traumatic
Hmm... wonder why everyone thanks ME since I only showed how to use prototypes...

Well, you're welcome anyway ;)

What is FMid2?

Posted: Wed Oct 25, 2006 3:11 pm
by Mikro
Sorry in advance if this question is really, really dumb.
What is FMid2 and where is it?
I just don't understand when the title mentions that we have a MID replacement? Where do you get this replacement?

Thanks a lot.

M.

Re: What is FMid2?

Posted: Wed Oct 25, 2006 3:48 pm
by traumatic