Hello Yrret,
took me a while to find the errors.
1.
Was my fault in the original test program, the line
Code: Select all
If tDiff >= 1: iEnd / tDiff: EndIf
should be
after the PrintN().
It was ment to keep the loop time under two second,
but used befor the print, it will give wrong result, because it
changes iEnd before the calculation of the operations per second.
2.
You use a 10 million in the test of Mid() and 1 million in the FMid2() test,
beside that, I posted the code with the already uncommented Mid() macro,
so
both tests used FMid2()
With this corrected, the test give a result of FMid2() being about 1.4 times
faster for the first test,
and 1.7 times faster for the second test.
My saying that FMid2() is 3-5 times faster is correct, but only for extracting short string from the end of longer strings (length over 1000),
If you don't mind the bigger size of, you can use the following procedure,
but it only improves the speed for the your first example to 1.41 times
and 1.8 times for the second, but it gives a better speed up for longer strings.
That's all one can do, if you don't know the string length in advance, it's sad that PB doesn't has string descriptors with the lenght of the string,
than it would be possible to speed up string functions by about 10 even
for short strings, for longer strings (over 1000) it would be immeasurable,
some 1000 times, because you could omit the silly scanning of the string from the start each time.
I can't understand why it is done this way, seems to be the 'C' way,
would be the same as if you scan an array each time, to see if you past the end.
Nuf rambling, here's the code:
Code: Select all
! macro EndMacro {} ; Just to keep the IDE folding happy
; Assembler macro to align code on a given boundary,
; aligning loop starts on 8 byte boundaries can speed up the code
; by about 1.5 to 2 times!
! macro calignjmp value
! {
! local dest
!
! if ((value - 1) - ((($ - $$) + value - 1) mod value)) > 3
! makeDest equ 1
! jmp dest
! else
! makeDest equ 0
! end if
!
! rept value
! \{
! if ($ - $$) mod value
! nop
! end if
! \}
! dest:
! } EndMacro
; Uncomment to use FMid() instead of Mid() as standard
; Macro Mid(string, start, length)
; FMid(@string,start,length)
; EndMacro
CompilerEndIf
CompilerIf #PB_Compiler_Unicode
Procedure.s FMid(*srcPtr.Byte, start.l, length.l)
!MOV edx,[p.p_srcPtr]
!MOV ecx,[p.v_length]
!TEST edx,edx
!JZ l_fmid_empty
!TEST ecx,ecx
!JLE l_fmid_empty
!MOV ecx,[p.v_start]
!CMP ecx,1
!JLE l_fmid_return
!XOR eax,eax
!calignjmp 8
fmid_scan1:
!SUB ecx,8
!JL l_fmid_scanend1_0
!CMP [edx],ax
!JE l_fmid_scanend2_1
!CMP [edx+2],ax
!JE l_fmid_scanend2_2
!CMP [edx+4],ax
!JE l_fmid_scanend2_3
!CMP [edx+6],ax
!JE l_fmid_scanend2_4
!CMP [edx+8],ax
!JE l_fmid_scanend2_5
!CMP [edx+10],ax
!JE l_fmid_scanend2_6
!CMP [edx+12],ax
!JE l_fmid_scanend2_7
!CMP [edx+14],ax
!JE l_fmid_scanend2_8
!ADD edx,16
!JMP l_fmid_scan1
fmid_scanend1_0:
!ADD ecx,8
!JNZ l_fmid_scan2
!SUB edx,2
!JMP l_fmid_scanend2_1
fmid_scan2:
!DEC ecx
!JZ l_fmid_scanend2_1
!CMP [edx],ax
!JZ l_fmid_scanend2_1
!DEC ecx
!JZ l_fmid_scanend2_2
!CMP [edx+2],ax
!JZ l_fmid_scanend2_2
!DEC ecx
!JZ l_fmid_scanend2_3
!CMP [edx+4],ax
!JZ l_fmid_scanend2_3
!DEC ecx
!JZ l_fmid_scanend2_4
!CMP [edx+6],ax
!JZ l_fmid_scanend2_4
!DEC ecx
!JZ l_fmid_scanend2_5
!CMP [edx+8],ax
!JZ l_fmid_scanend2_5
!DEC ecx
!JZ l_fmid_scanend2_6
!CMP [edx+10],ax
!JZ l_fmid_scanend2_6
!JMP l_fmid_scanend2_7
fmid_scanend2_8:
!ADD edx,14
!JMP l_fmid_scanend2_1
fmid_scanend2_7:
!ADD edx,12
!JMP l_fmid_scanend2_1
fmid_scanend2_6:
!ADD edx,10
!JMP l_fmid_scanend2_1
fmid_scanend2_5:
!ADD edx,8
!JMP l_fmid_scanend2_1
fmid_scanend2_4:
!ADD edx,6
!JMP l_fmid_scanend2_1
fmid_scanend2_3:
!ADD edx,4
!JMP l_fmid_scanend2_1
fmid_scanend2_2:
!ADD edx,2
fmid_scanend2_1:
!MOV [p.p_srcPtr],edx
fmid_return:
ProcedureReturn PeekS(*srcPtr, length)
fmid_empty:
ProcedureReturn ""
EndProcedure
CompilerElse
Procedure.s FMid(*srcPtr.Byte, start.l, length.l)
!MOV edx,[p.p_srcPtr]
!MOV ecx,[p.v_length]
!TEST edx,edx
!JZ l_fmid_empty
!TEST ecx,ecx
!JLE l_fmid_empty
!MOV ecx,[p.v_start]
!CMP ecx,1
!JLE l_fmid_return
!XOR eax,eax
!calignjmp 8
fmid_scan1:
!SUB ecx,8
!JL l_fmid_scanend1_0
!CMP [edx],al
!JE l_fmid_scanend2_1
!CMP [edx+1],al
!JE l_fmid_scanend2_2
!CMP [edx+2],al
!JE l_fmid_scanend2_3
!CMP [edx+3],al
!JE l_fmid_scanend2_4
!CMP [edx+4],al
!JE l_fmid_scanend2_5
!CMP [edx+5],al
!JE l_fmid_scanend2_6
!CMP [edx+6],al
!JE l_fmid_scanend2_7
!CMP [edx+7],al
!JE l_fmid_scanend2_8
!ADD edx,8
!JMP l_fmid_scan1
fmid_scanend1_0:
!ADD ecx,8
!JNZ l_fmid_scan2
!DEC edx
!JMP l_fmid_scanend2_1
fmid_scan2:
!DEC ecx
!JZ l_fmid_scanend2_1
!CMP [edx],al
!JZ l_fmid_scanend2_1
!DEC ecx
!JZ l_fmid_scanend2_2
!CMP [edx+1],al
!JZ l_fmid_scanend2_2
!DEC ecx
!JZ l_fmid_scanend2_3
!CMP [edx+2],al
!JZ l_fmid_scanend2_3
!DEC ecx
!JZ l_fmid_scanend2_4
!CMP [edx+3],al
!JZ l_fmid_scanend2_4
!DEC ecx
!JZ l_fmid_scanend2_5
!CMP [edx+4],al
!JZ l_fmid_scanend2_5
!DEC ecx
!JZ l_fmid_scanend2_6
!CMP [edx+5],al
!JZ l_fmid_scanend2_6
!JMP l_fmid_scanend2_7
fmid_scanend2_8:
!ADD edx,7
!JMP l_fmid_scanend2_1
fmid_scanend2_7:
!ADD edx,6
!JMP l_fmid_scanend2_1
fmid_scanend2_6:
!ADD edx,5
!JMP l_fmid_scanend2_1
fmid_scanend2_5:
!ADD edx,4
!JMP l_fmid_scanend2_1
fmid_scanend2_4:
!ADD edx,3
!JMP l_fmid_scanend2_1
fmid_scanend2_3:
!ADD edx,2
!JMP l_fmid_scanend2_1
fmid_scanend2_2:
!ADD edx,1
fmid_scanend2_1:
!MOV [p.p_srcPtr],edx
fmid_return:
ProcedureReturn PeekS(*srcPtr, length)
fmid_empty:
ProcedureReturn ""
EndProcedure
CompilerEndIf