 |
Bay Six Software Beyond the Basics
|
View previous topic :: View next topic |
Author |
Message |
Brent Site Admin
Joined: 01 Jul 2005 Posts: 793
|
Posted: Nov 9th, 2007, 5:20am Post subject: [BETA] Large Strings Library |
|
|
Below is a library that improves the speed of LB code that manipulates large strings. Strings larger than 3-4KB can be modified more quickly with this library that LB's own native code. Below that threshold, the overhead of the calls becomes great enough to make it slower than LB native code.
The main reason for the speed improvement is due to its doing its own memory management. The string is allocated statically at a fixed size that cannot be modified. Attempting to overflow the string results in clipping.
First is a little test driver, then the actual library, then finally an equivalent program to the first two using native code and my old QBMID routine from the "Snips" section. On my system, the library's driver is more than one second faster than the native code example.
Code: | ITERATIONS = 40
STRINGSIZE = 4000
t = Time$("ms")
aString = NewStr(STRINGSIZE)
For i = 1 To ITERATIONS
For c = 1 To STRINGSIZE
Call MidStrN aString, c, 1, "X"
Next c
Next i
Call KillStr aString
Print Time$("ms") - t
End |
Code: | '== Large String Library
'== By Brent D. Thorn, 11/2007
Function NewStr( Size )
'-- Creates a new string of a given size.
'-- Paramters
' Size - number of bytes
'-- Returns
' a pointer to the string or NULL
Struct cbStr, cb As ULong
Global g.hProcessHeap
CallDLL #kernel32, "GetProcessHeap", g.hProcessHeap As ULong
If Size < 1 Then Exit Function
cbHeap = Size + 4
CallDLL #kernel32, "HeapAlloc", g.hProcessHeap As ULong, 0 As ULong, cbHeap As ULong, NewStr As ULong
cbStr.cb.struct = 0
CallDLL #kernel32, "RtlMoveMemory", NewStr As ULong, cbStr As Struct, 4 As ULong, ret As Void
End Function
Sub KillStr pStr
'-- Destroys a string created by 'NewStr'
'-- Parameters
' pStr - a pointer to a string
CallDLL #kernel32, "HeapFree", g.hProcessHeap As ULong, 0 As ULong, pStr As ULong, ret As Long
End Sub
Function LenStr( pStr )
'-- Equivalent of the LEN function
'-- Parameters
' pStr - a pointer to a string created by 'NewStr'
'-- Returns
' the length of the string in bytes
'[safe] CallDLL #kernel32, "RtlMoveMemory", cbStr As Struct, pStr As ULong, 4 As ULong, ret As Void
cbStr.struct = pStr '[unsafe]
LenStr = cbStr.cb.struct
End Function
Sub LetStr pDst, Src$
'-- Equivalent of LET for a string created by 'NewStr'
'-- Paramters
' pDst - a pointer to the string to be assigned a new value
' Src$ - a string that holds the new value to be assigned
CallDLL #kernel32, "HeapSize", g.hProcessHeap As ULong, 0 As ULong, pDst As ULong, cbHeap As ULong
pStr = pDst + 4
cbSrc = Min(cbHeap - 4, Len(Src$))
CallDLL #kernel32, "RtlMoveMemory", pStr As ULong, Src$ As Ptr, cbSrc As ULong, ret As Void
cbStr.cb.struct = cbSrc
CallDLL #kernel32, "RtlMoveMemory", pDst As ULong, cbStr As Struct, 4 As ULong, ret As Void
End Sub
Sub CatStr pDst, Src$
'-- Concatenates a string onto a string created by 'NewStr'
'-- Parameters
' pDst - a pointer to a string to be modified
' Src$ - a string to be concatenated
CallDLL #kernel32, "HeapSize", g.hProcessHeap As ULong, 0 As ULong, pDst As ULong, cbHeap As ULong
'[safe] CallDLL #kernel32, "RtlMoveMemory", cbStr As Struct, pDst As ULong, 4 As ULong, ret As Void
cbStr.struct = pDst '[unsafe]
cbDst = cbStr.cb.struct
cbSrc = Min(cbHeap - 4 - cbDst, Len(Src$))
pStr = pDst + 4 + cbDst
CallDLL #kernel32, "RtlMoveMemory", pStr As ULong, Src$ As Ptr, cbSrc As ULong, ret As Void
cbStr.cb.struct = cbDst + cbSrc
CallDLL #kernel32, "RtlMoveMemory", pDst As ULong, cbStr As Struct, 4 As ULong, ret As Void
End Sub
Function GetStr$( pStr )
'-- Somewhat equivalent to WINSTRING
'-- Parameters
' pStr - a pointer to a string created by 'NewStr'
'-- Returns
' the string value regardless of NUL characters
'[safe] CallDLL #kernel32, "RtlMoveMemory", cbStr As Struct, pStr As ULong, 4 As ULong, ret As Void
cbStr.struct = pStr '[unsafe]
cbStr = cbStr.cb.struct
GetStr$ = Space$(cbStr)
pStr = pStr + 4
CallDLL #kernel32, "RtlMoveMemory", GetStr$ As Ptr, pStr As ULong, cbStr As ULong, ret As Void
End Function
Sub MidStr pDst, Pos, Src$
'-- Equivalent to QB's MID$ statement with two params
' E.g. MID$(d$, p) = s$
'[safe] CallDLL #kernel32, "RtlMoveMemory", cbStr As Struct, pDst As ULong, 4 As ULong, ret As Void
cbStr.struct = pDst '[unsafe]
cbDst = cbStr.cb.struct
pDst = pDst + 3 + Pos
cnt = Len(Src$)
If Pos + cnt > cbDst Then _
cnt = cbDst - Pos + 1
If cnt > 0 Then _
CallDLL #kernel32, "RtlMoveMemory", pDst As ULong, Src$ As Ptr, cnt As ULong, ret As Void
End Sub
Sub MidStrN pDst, Pos, Cnt, Src$
'-- Equivalent to QB's MID$ statement with three params
' E.g. MID$(d$, p, c) = s$
'[safe] CallDLL #kernel32, "RtlMoveMemory", cbStr As Struct, pDst As ULong, 4 As ULong, ret As Void
cbStr.struct = pDst '[unsafe]
cbDst = cbStr.cb.struct
pDst = pDst + 3 + Pos
If Cnt > Len(Src$) Then Cnt = Len(Src$)
If Pos + Cnt > cbDst Then _
Cnt = cbDst - Pos + 1
If Cnt > 0 Then _
CallDLL #kernel32, "RtlMoveMemory", pDst As ULong, Src$ As Ptr, Cnt As ULong, ret As Void
End Sub |
Code: | ITERATIONS = 40
STRINGSIZE = 4000
t = Time$("ms")
a$ = Space$(STRINGSIZE)
For i = 1 To ITERATIONS
For c = 1 To STRINGSIZE
Call QBMID a$, c, 1, "X"
Next c
Next i
Print Time$("ms") - t
End
Sub QBMID ByRef Dst$, Pos, Cnt, Src$
'-- Equivalent to QB's MID$(d$,p,c)=s$ command.
'-- Usage: Call QBMID d$,p,c,s$
'-- Provided freely by Brent D. Thorn.
'-- http://www.b6sw.com
If Cnt > Len(Src$) Then Cnt = Len(Src$)
If Pos + Cnt > Len(Dst$) Then _
Cnt = Len(Dst$) - Pos + 1
If Cnt > 0 Then
Dst$ = Left$(Dst$, Pos - 1) _
+ Left$(Src$, Cnt) _
+ Mid$(Dst$, Pos + Cnt)
End If
End Sub |
_________________ Brent |
|
Back to top |
|
 |
hans Guest
|
Posted: Apr 1st, 2009, 7:37am Post subject: Getting string from memoryblock (large string library) |
|
|
I made a additional function for the large string library. It gets a string from anywhere in the memoryblock created by NewStr.
There is just one problem: the string GetStr$ doesnt have the content after the kernel is called, it is still a string filled with spaces.
What am I doing wrong?
Code: | Function GetStr$(pStr,Pos,cnt,leng)
'-- Get a string out off a memoryblock created by 'NewStr'
'-- Parameters
' pStr - a pointer to the start of the memoryblock
' pos - offset from start of memoryblock
' cnt - required length of string GetStr$
' leng - length memoryblock (pStr)
'-- Returns
' the string value regardless of NUL characters
GetStr$ = Space$(cnt) '**
Src = pStr + 3 + Pos
if Pos+cnt-1>leng then cnt=leng - Pos + 1
CallDLL #kernel32, "RtlMoveMemory", GetStr$ As Ptr, Src As ULong, cnt As ULong, ret As Void
End Function
|
|
|
Back to top |
|
 |
Guest
|
Posted: Apr 1st, 2009, 10:30am Post subject: Re: [BETA] Large Strings Library |
|
|
Has it something to do with what you do in other routines?:
[/code]cbStr.struct = pDst '[unsafe]
cbDst = cbStr.cb.struct Code: |
I don't have any idea what this code does.
hans |
|
|
Back to top |
|
 |
Brent Site Admin
Joined: 01 Jul 2005 Posts: 793
|
Posted: Apr 1st, 2009, 7:28pm Post subject: Re: [BETA] Large Strings Library |
|
|
Hello Hans,
I think you want something like this.
Code: | Function MidStrN$( pStr, Pos, Cnt )
'-- Equivalent to the "Mid$" function with 3 parameters
If Pos < 1 Or Cnt < 1 Then Exit Function
cbStr.struct = pStr '[unsafe]
cbStr = cbStr.cb.struct
cbMid = Min(Cnt, cbStr - Pos - 1)
If cbMid < 1 Then Exit Function
MidStrN$ = Space$(cbMid)
pStr = pStr + Pos + 3
CallDLL #kernel32, "RtlMoveMemory", MidStrN$ As Ptr, pStr As ULong, cbMid As ULong, ret As Void
End Function |
The cbStr variable holds the count of bytes in the string, which is stored at the start if the memory block. _________________ Brent |
|
Back to top |
|
 |
|
|
|
|
|
You cannot post new topics in this forum You can reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum You cannot attach files in this forum You can download files in this forum
|
|