MidFast() - A much faster Mid() alternative

Share your advanced PureBasic knowledge/code with the community.
c4s
Addict
Addict
Posts: 1981
Joined: Thu Nov 01, 2007 5:37 pm
Location: Germany

MidFast() - A much faster Mid() alternative

Post by c4s »

MidFast() is faster than Mid() in general use and gets thousand times faster with very large texts (try #TestLen=2500, #TestCount=1): The longer the text, the faster MidFast() gets...

Code: Select all

#TestLen = 10
#TestCount = 10000

Define Text.s, C.s, i, iMax


For i = 1 To #TestLen
	Text + "testTesttEsttestTESTtesttestteSt"
Next

ts1 = ElapsedMilliseconds()
For j = 1 To #TestCount
i = 0
iMax = Len(Text)
Repeat
	i + 1
	C = Mid(Text, i, 1)
Until i >= iMax
Next
te1 = ElapsedMilliseconds()


Macro MidFast(String, StartPos, Length)
	PeekS(@String + ((StartPos - 1) * SizeOf(Character)), Length)
EndMacro

ts2 = ElapsedMilliseconds()
For j = 1 To #TestCount
i = 0
iMax = Len(Text)
Repeat
	i + 1
	C = MidFast(Text, i, 1)
Until i >= iMax
Next
te2 = ElapsedMilliseconds()


MessageRequester("Result", "Mid() - " + Str(te1 - ts1) + #CRLF$ + "MidFast() - " + Str(te2 - ts2))
Edit:
Trond notes that it's just faster because this method doesn't check for valid position/length, so keep that in mind...
Last edited by c4s on Thu Feb 03, 2011 8:06 pm, edited 1 time in total.
If any of you native English speakers have any suggestions for the above text, please let me know (via PM). Thanks!
cas
Enthusiast
Enthusiast
Posts: 597
Joined: Mon Nov 03, 2008 9:56 pm

Re: MidFast() - A much faster Mid() alternative

Post by cas »

c4s wrote:Does anyone know what internal parameter PeekS() uses to determine that "Length" isn't set? Unluckily it doesn't seem to be #PB_Default
It is #PB_Default (-1), but you can set it to -1 only if you specify 'Flags' parameter:
PB Manual wrote:When the 'Flags' parameter is specified, the 'Length' can be put to -1, to read the string until a null character is found.

Code: Select all

Macro MidFast(String, StartPos, Length=-1,Mode=#PB_Ascii)
  PeekS(@String + ((StartPos - 1) * SizeOf(Character)), Length, Mode)
EndMacro
c4s
Addict
Addict
Posts: 1981
Joined: Thu Nov 01, 2007 5:37 pm
Location: Germany

Re: MidFast() - A much faster Mid() alternative

Post by c4s »

Oh well... Thanks for the hint. I thought I've tested it.
If any of you native English speakers have any suggestions for the above text, please let me know (via PM). Thanks!
User avatar
skywalk
Addict
Addict
Posts: 4211
Joined: Wed Dec 23, 2009 10:14 pm
Location: Boston, MA

Re: MidFast() - A much faster Mid() alternative

Post by skywalk »

Well, this MidFast() is the same or slower than Mid() on my x86 system with the optional parameters included?
No debugger and either unicode=ON or OFF.
User avatar
STARGÅTE
Addict
Addict
Posts: 2227
Joined: Thu Jan 10, 2008 1:30 pm
Location: Germany, Glienicke
Contact:

Re: MidFast() - A much faster Mid() alternative

Post by STARGÅTE »

Youre Macro with Unicode:

Code: Select all

Macro MidFast(String, StartPos, Length=-1,Mode=#PB_Ascii)
  PeekS(@String + ((StartPos - 1) * SizeOf(Character)), Length, Mode)
EndMacro 
String.s = "HalloWorldHallo"
Debug MidFast(String, 6, 5)
Debug Mid(String, 6, 5)
W
World
so, its better to use:

Code: Select all

CompilerIf #PB_Compiler_Unicode
  Macro MidFast(String, StartPos, Length=-1)
    PeekS(@String + ((StartPos - 1) * SizeOf(Character)), Length, #PB_Unicode)
  EndMacro 
CompilerElse
  Macro MidFast(String, StartPos, Length=-1)
    PeekS(@String + ((StartPos - 1) * SizeOf(Character)), Length, #PB_Ascii)
  EndMacro  
CompilerEndIf

String.s = "HalloWorldHallo"
Debug MidFast(String, 6, 5)
Debug Mid(String, 6, 5)
Debug MidFast(String, 6)
Debug Mid(String, 6)
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Lizard - Script language for symbolic calculations and moreTypeface - Sprite-based font include/module
User avatar
Guimauve
Enthusiast
Enthusiast
Posts: 742
Joined: Wed Oct 22, 2003 2:51 am
Location: Canada

Re: MidFast() - A much faster Mid() alternative

Post by Guimauve »

skywalk wrote:Well, this MidFast() is the same or slower than Mid() on my x86 system with the optional parameters included?
No debugger and either unicode=ON or OFF.
Yes me too, on my Linux Ubuntu x64. But when I change the "Length" to 1 instead of -1 The MidFast() it's much faster than Mid() function.

Result with Length = -1

- Mid() - 583
- MidFast() - 1587

Result with Length = 1

- Mid() - 592
- MidFast() - 120

No debbuger in both case.

Best regards.
Guimauve
User avatar
skywalk
Addict
Addict
Posts: 4211
Joined: Wed Dec 23, 2009 10:14 pm
Location: Boston, MA

Re: MidFast() - A much faster Mid() alternative

Post by skywalk »

Thanks STARGÅTE!
MidFast() is only slower when the Length = -1, not sure why, but it is worth the extra speed for other cases.
This now makes sense to use. :)
c4s
Addict
Addict
Posts: 1981
Joined: Thu Nov 01, 2007 5:37 pm
Location: Germany

Re: MidFast() - A much faster Mid() alternative

Post by c4s »

STARGÅTE wrote:so, its better to use:

Code: Select all

CompilerIf #PB_Compiler_Unicode
  Macro MidFast(String, StartPos, Length=-1)
    PeekS(@String + ((StartPos - 1) * SizeOf(Character)), Length, #PB_Unicode)
  EndMacro 
CompilerElse
  Macro MidFast(String, StartPos, Length=-1)
    PeekS(@String + ((StartPos - 1) * SizeOf(Character)), Length, #PB_Ascii)
  EndMacro  
CompilerEndIf

String.s = "HalloWorldHallo"
Debug MidFast(String, 6, 5)
Debug Mid(String, 6, 5)
Debug MidFast(String, 6)
Debug Mid(String, 6)
PureBasic does this automatically so the mode parameter isn't needed at all and if it's slower with "-1" for length then better don't use it, so that it will remind you.
If any of you native English speakers have any suggestions for the above text, please let me know (via PM). Thanks!
Vitor_Boss®
User
User
Posts: 81
Joined: Thu Sep 23, 2010 4:22 am

Re: MidFast() - A much faster Mid() alternative

Post by Vitor_Boss® »

Code: Select all

#TestLen = 10
#TestCount = 1000
Define Text.s, C.s, C1.s, i, iMax
For i = 1 To #TestLen
   Text + "testTesttEsttestTESTtesttestteSt"
Next
ts1 = ElapsedMilliseconds()
For j = 1 To #TestCount
i = 0
iMax = Len(Text)
Repeat
   i + 1
   C1 = Mid(Text, i)
Until i >= iMax
Next
te1 = ElapsedMilliseconds()
CompilerIf #PB_Compiler_Unicode
  Macro MidFast(String, StartPos, Length=-1)
    PeekS(@String + ((StartPos - 1) * SizeOf(Character)), Length, #PB_Unicode)
  EndMacro 
CompilerElse
  Macro MidFast(String, StartPos, Length=-1)
    PeekS(@String + ((StartPos - 1) * SizeOf(Character)), Length, #PB_Ascii)
  EndMacro  
CompilerEndIf
ts2 = ElapsedMilliseconds()
For j = 1 To #TestCount
i = 0
iMax = Len(Text)
Repeat
   i + 1
   C = MidFast(Text, i)
Until i >= iMax
Next
te2 = ElapsedMilliseconds()
MessageRequester("Result", "Mid() - " + Str(te1 - ts1) + #CRLF$ + "MidFast() - " + Str(te2 - ts2) + #CRLF$ + #CRLF$ + "Text = C : "+Str(C=C1))
On my PC(Win7 x64) the MidFast was faster on both cases
Result with Length = -1
- Mid() - 468
- MidFast() - 312

Result with Length = 1
- Mid() - 102
- MidFast() - 31
Sorry by bad English.
HP Pavilion DV6-2155DX: Intel i3-330m 2.13 / 4GB DDR3 / 500GB Sata2 HD / Display 15.6" LED / Win7 Ultimate x64 / PB 4.50 x86 demo.
IdeasVacuum
Always Here
Always Here
Posts: 6426
Joined: Fri Oct 23, 2009 2:33 am
Location: Wales, UK
Contact:

Re: MidFast() - A much faster Mid() alternative

Post by IdeasVacuum »

... I wonder if pcfreak could make an even faster MidFast with assembler?

http://www.purebasic.fr/english/viewtop ... 85#p345585
IdeasVacuum
If it sounds simple, you have not grasped the complexity.
Trond
Always Here
Always Here
Posts: 7446
Joined: Mon Sep 22, 2003 6:45 pm
Location: Norway

Re: MidFast() - A much faster Mid() alternative

Post by Trond »

Just a side note: The reason the normal Mid() is slow is because it does bound checking (so you don't access memory outside the string). To use a Mid() without bound checking safely you would most often need to check the length beforehand, which would nullify the speed gain.
User avatar
skywalk
Addict
Addict
Posts: 4211
Joined: Wed Dec 23, 2009 10:14 pm
Location: Boston, MA

Re: MidFast() - A much faster Mid() alternative

Post by skywalk »

c4s wrote:Note: Passing constant strings (like "text") doesn't work because it's a macro.
What do you mean "doesn't work"?

Code: Select all

CompilerIf #PB_Compiler_Unicode
  Macro MidFast(String, StartPos, Length=-1)
    PeekS(@String + ((StartPos - 1) * SizeOf(Character)), Length, #PB_Unicode)
  EndMacro 
CompilerElse
  Macro MidFast(String, StartPos, Length=-1)
    PeekS(@String + ((StartPos - 1) * SizeOf(Character)), Length, #PB_Ascii)
  EndMacro  
CompilerEndIf
Define.s C, Text = "Text"
C = MidFast(Text, 2):   Debug C
C = MidFast("Text", 2): Debug C     ;<-- This works on v4.51 x86
The nice thing about standards is there are so many to choose from. ~ Andrew Tanenbaum
c4s
Addict
Addict
Posts: 1981
Joined: Thu Nov 01, 2007 5:37 pm
Location: Germany

Re: MidFast() - A much faster Mid() alternative

Post by c4s »

Seems that I did something wrong during my testings, now it works here as well. I edited my first post to not confuse others and also added Trond's note.
If any of you native English speakers have any suggestions for the above text, please let me know (via PM). Thanks!
Post Reply