Page 2 of 5

Re: Fast string

Posted: Sat Mar 29, 2014 9:15 am
by User_Russian
STARGÅTE wrote:Fast string is implimented es CopyMemoryString()
This function does not allocate memory for the string.
Then it is not much different from PokeS().
In addition, its use does not accelerate the string functions, such as for example FindString(). In which takes a long time to measure the length of the string.

Re: Fast string

Posted: Sat Mar 29, 2014 9:31 am
by User_Russian
Perhaps not everyone understands that it is by measuring the length of the string, reduces the speed of execution.

Suppose that it is work with a string without measuring its length.

Code: Select all

DisableDebugger

Time = ElapsedMilliseconds()

For i=1 To 100000
Next i

MessageRequester("", StrF((ElapsedMilliseconds()-Time)/1000, 3))
This length measurement (assume that every time a string is added to 10 characters).

Code: Select all

DisableDebugger

Time = ElapsedMilliseconds()

Len = 10

For i=1 To 100000
  
  For y=1 To Len : Next y ; Analog of function Len().
  
  Len + 10
Next i

MessageRequester("", StrF((ElapsedMilliseconds()-Time)/1000, 3))
Compare speed of execution.

Re: Fast string

Posted: Mon Mar 31, 2014 8:48 am
by Thorium
I think it would be very nice to have fast strings.
Just as User_Russian wrote, add a length descriptor to every string. Makes strings use more memory, but today memory is no issue, speed is more importent in most cases.

Re: Fast string

Posted: Mon Mar 31, 2014 9:51 am
by User_Russian
Thorium wrote:Makes strings use more memory,
String is longer by 4 bytes in x86, and longer by 8 bytes in x64.

Re: Fast string

Posted: Sun Apr 06, 2014 8:06 pm
by langinagel
Gentlemen,

the code below yield the following result on my PC (asus laptop with lubuntu):
10 0.000
100 0.000
1000 0.014
10000 1.125
100000 125.365

This means that for strings below 1000 characters the speed of processing sufficient high from my point of view. I think the majority of processed strings are inputs from forms that have less than 1000 characters.

My suggestion:
If we need faster strings a second class of "longstrings" should be defined with the length attached. This should be the real feature request.
But the usual string should be kept. Why?
Because in cases of memory faults, maybe in the string length bytes, the processing will fail and/or we might have a security problem.

Comments?

Code: Select all

OpenConsole()
Str.s
#Text = "1234567890"
mstart =1
y =  Int(Pow(10,mstart))
Time = ElapsedMilliseconds()

For i=1 To 100010
  Str + #Text
  If i = y
    PrintN(Str(i)+"           "+StrF((ElapsedMilliseconds()-Time)/1000, 3))
    mstart = mstart + 1
    y = Int(Pow(10,mstart))
    Time = ElapsedMilliseconds()
  EndIf
  
Next i
Print( "ende")
Input()

Greetings
LN

Re: Fast string

Posted: Mon Apr 07, 2014 7:50 am
by User_Russian
This problem refers to the string functions.
Compare the speed of these two codes.

Code: Select all

OpenConsole()
Str.s = Space(100010)
mstart =1
y =  Int(Pow(10,mstart))
Time = ElapsedMilliseconds()
Pos=0
For i=1 To 100010
  
  s.s=Mid(Str, i, 1)
  If i = y
    PrintN(Str(i)+"           "+StrF((ElapsedMilliseconds()-Time)/1000, 3))
    mstart = mstart + 1
    y = Int(Pow(10,mstart))
    Time = ElapsedMilliseconds()
  EndIf
  
Next i
Print( "ende")
Input()

Code: Select all

OpenConsole()
Str.s = Space(100010)
mstart =1
y =  Int(Pow(10,mstart))
Time = ElapsedMilliseconds()
Pos=0
For i=1 To 100010
  
  s.s=PeekS(@Str+i, 1)
  If i = y
    PrintN(Str(i)+"           "+StrF((ElapsedMilliseconds()-Time)/1000, 3))
    mstart = mstart + 1
    y = Int(Pow(10,mstart))
    Time = ElapsedMilliseconds()
  EndIf
  
Next i
Print( "ende")
Input()

Re: Fast string

Posted: Mon Apr 07, 2014 6:18 pm
by langinagel
UR,

the comparison yields on my PC (core3 with Ubuntu12.04 -x68) to:
#repeats code above code below
10 0.000 0.000
100 0.000 0.000
1000 0.000 0.000
10000 0.044 0.000
100000 3.431 0.006

Again: for strings of the length of 50KB and below I see no need for change.

For a dedicated long-string, I agree to the new feature.
But: the basic routine should contain a check: if the string-end marking could not be found at the attached byte offset then the string should have a dedicated error marking(e.g. negative string length).

Comments?

Greetings
LN

Re: Fast string

Posted: Wed Apr 09, 2014 8:44 am
by User_Russian
Can add new functions

Code: Select all

StringVerificationLength(String.s)
which will measure the length of the string and write it the correct value.

Re: Fast string

Posted: Thu Apr 10, 2014 11:10 am
by Opcode
I agree, I am working on a project right now and the slowness of PB's string handling is effecting it's responsiveness. Something that should be improved for the future.

Re: Fast string

Posted: Fri Mar 17, 2017 11:45 am
by Andre
As I'm also working a lot with .csv files and following string operations I would be very happy too, if the native implementation could be optimized! :mrgreen:

Re: Fast string

Posted: Sat Mar 18, 2017 11:47 am
by gurj
'strings in PB, very slow'
'Just as User_Russian wrote, add a length descriptor to every string'

PB must let .s=.BSTR inside pb internal ,for each string:

.s add size.l:

Structure BSTR
size.l ;"ABC" = 3 (Asc) or 6 (unicode)
s.s ;Never directly WRITE to this; always use bFunctions() to ensure \Size is updated.
EndStructure

then optimize more :
len(string$)=string$\size
...

see :
BSTR* fast dynamic string datatype
http://www.purebasic.fr/english/viewtop ... 12&t=68121

Re: Fast string

Posted: Fri Mar 24, 2017 12:27 pm
by marcoagpinto
+1

In my Hunspell tool, "Proofing Tool GUI", I have tons of string operations and I notice the slowness.

Re: Fast string

Posted: Sat Mar 25, 2017 1:57 am
by Thunder93
Keya really have done up an impressive demonstration. Really makes apparent the need for faster string.

I hope User_Russian gets his wish fulfilled.

+1 for me

Re: Fast string

Posted: Sat Mar 25, 2017 2:30 am
by ShadowStorm
I do not know if this is what you want:

Code: Select all

Structure MyStringBuilder
 
  MyStringBuilderAllocateMemory.B
  *MyStringBuilderMemoryID
  MyStringBuilderSize.I
  MyStringBuilderRemaining.I
  MyStringBuilderPosition.I
 
EndStructure

Global MyStringBuilder.MyStringBuilder

Procedure.B IsStringBuilder()
 
  If MyStringBuilder\MyStringBuilderAllocateMemory = #True And MyStringBuilder\MyStringBuilderMemoryID <> 0
    ProcedureReturn  1
   
  Else
    ProcedureReturn 0
   
  EndIf
 
EndProcedure

Procedure.I InitialiseStringBuilder(Taille.I = 1000)
 
  If Taille.I <= 0
    Taille.I = 1
  EndIf
 
  If Not IsStringBuilder()
   
    MyStringBuilder\MyStringBuilderMemoryID = AllocateMemory(Taille.I)
   
    If MyStringBuilder\MyStringBuilderMemoryID <> 0
     
      MyStringBuilder\MyStringBuilderAllocateMemory = #True
      MyStringBuilder\MyStringBuilderRemaining = MemorySize(MyStringBuilder\MyStringBuilderMemoryID)
      MyStringBuilder\MyStringBuilderSize = MemorySize(MyStringBuilder\MyStringBuilderMemoryID)
      MyStringBuilder\MyStringBuilderPosition = 0
     
      ProcedureReturn MyStringBuilder\MyStringBuilderRemaining
     
    Else
      ProcedureReturn 0
     
    EndIf
   
  Else
    ProcedureReturn 0
   
  EndIf
 
EndProcedure

Procedure.B StringBuilderClearString(Taille.I = 1000)
 
  If Taille.I <= 0
    Taille.I = 1
  EndIf
 
  If IsStringBuilder()
   
    FreeMemory(MyStringBuilder\MyStringBuilderMemoryID)
   
    MyStringBuilder\MyStringBuilderAllocateMemory = #False
    MyStringBuilder\MyStringBuilderMemoryID = 0
    MyStringBuilder\MyStringBuilderSize = 0
    MyStringBuilder\MyStringBuilderRemaining = 0
    MyStringBuilder\MyStringBuilderPosition = 0
   
    If InitialiseStringBuilder(Taille.I)
      ProcedureReturn 1
     
    Else
      ProcedureReturn 0
     
    EndIf
   
  Else
    ProcedureReturn 0
   
  EndIf
 
EndProcedure

Procedure.I StringBuilderAddString(String.s)
 
  If IsStringBuilder()
   
    If Len(String.s) > MyStringBuilder\MyStringBuilderRemaining.I
     
      MyStringBuilder\MyStringBuilderMemoryID = ReAllocateMemory(MyStringBuilder\MyStringBuilderMemoryID, MemorySize(MyStringBuilder\MyStringBuilderMemoryID) + (Len(String.s) * 10))
     
      If MyStringBuilder\MyStringBuilderMemoryID <> 0
       
        MyStringBuilder\MyStringBuilderRemaining = MemorySize(MyStringBuilder\MyStringBuilderMemoryID) - MyStringBuilder\MyStringBuilderPosition
        MyStringBuilder\MyStringBuilderSize = MemorySize(MyStringBuilder\MyStringBuilderMemoryID)
       
        OctetsWrite = PokeS(MyStringBuilder\MyStringBuilderMemoryID + MyStringBuilder\MyStringBuilderPosition, String.s, -1, #PB_Ascii | #PB_String_NoZero)
       
        MyStringBuilder\MyStringBuilderRemaining - OctetsWrite
        MyStringBuilder\MyStringBuilderPosition + OctetsWrite
       
        ProcedureReturn OctetsWrite
       
      Else
        ProcedureReturn 0
       
      EndIf
     
    Else
     
      OctetsWrite = PokeS(MyStringBuilder\MyStringBuilderMemoryID + MyStringBuilder\MyStringBuilderPosition, String.s, -1, #PB_Ascii | #PB_String_NoZero)
     
      MyStringBuilder\MyStringBuilderRemaining - OctetsWrite
      MyStringBuilder\MyStringBuilderPosition + OctetsWrite
     
      ProcedureReturn OctetsWrite
     
    EndIf
   
  Else
    ProcedureReturn 0
   
  EndIf
 
EndProcedure

Procedure.S StringBuilderGetString()
 
  If IsStringBuilder()
    ProcedureReturn PeekS(MyStringBuilder\MyStringBuilderMemoryID)
   
  Else
    ProcedureReturn ""
   
  EndIf
 
EndProcedure

Procedure.I StringBuilderGetMemoryID()
 
  If IsStringBuilder()
    ProcedureReturn MyStringBuilder\MyStringBuilderMemoryID
   
  Else
    ProcedureReturn 0
   
  EndIf
 
EndProcedure

Procedure.I StringBuilderGetMemorySize()
 
  If IsStringBuilder()
    ProcedureReturn MyStringBuilder\MyStringBuilderSize
   
  Else
    ProcedureReturn 0
   
  EndIf
 
EndProcedure

Procedure.I StringBuilderGetMemoryRemaining()
 
  If IsStringBuilder()
    ProcedureReturn MyStringBuilder\MyStringBuilderRemaining
   
  Else
    ProcedureReturn 0
   
  EndIf
 
EndProcedure

Procedure.I StringBuilderGetMemoryPosition()
 
  If IsStringBuilder()
    ProcedureReturn MyStringBuilder\MyStringBuilderPosition
   
  Else
    ProcedureReturn 0
   
  EndIf
 
EndProcedure

Abc$ = "Abcdefghijklmnopqrstuvwxyz"

If InitialiseStringBuilder() And IsStringBuilder()
 
  MessageRequester("StringBuilder Initialisation...", "StringBuilder MemoryID = " + Str(StringBuilderGetMemoryID()) + Chr(13) + Chr(10) +
                                                      "StringBuilder Memory Size = " + Str(StringBuilderGetMemorySize()) + Chr(13) + Chr(10) +
                                                      "StringBuilder Memory Remaining = " + Str(StringBuilderGetMemoryRemaining()) + Chr(13) + Chr(10) +
                                                      "StringBuilder Memory Position = " + Str(StringBuilderGetMemoryPosition()))
 
  Time1 = ElapsedMilliseconds()
 
  For I = 1 To 100000
   
    MemoryID = StringBuilderGetMemoryID()
    MemorySize = StringBuilderGetMemorySize()
    MemoryRemaining = StringBuilderGetMemoryRemaining()
    MemoryPosition = StringBuilderGetMemoryPosition()
    OctetsWrite = StringBuilderAddString(Abc$)
   
  Next
 
  Time2 = ElapsedMilliseconds()
 
  MessageRequester("StringBuilder Résultat...", "StringBuilder MemoryID = " + Str(StringBuilderGetMemoryID()) + Chr(13) + Chr(10) +
                                                "StringBuilder Memory Size = " + Str(StringBuilderGetMemorySize()) + Chr(13) + Chr(10) +
                                                "StringBuilder Memory Remaining = " + Str(StringBuilderGetMemoryRemaining()) + Chr(13) + Chr(10) +
                                                "StringBuilder Memory Position = " + Str(StringBuilderGetMemoryPosition()) + Chr(13) + Chr(10) +
                                                "StringBuilder Last Octets Write = " + Str(OctetsWrite) + Chr(13) + Chr(10) +
                                                "Time Elapsed = " + Str(Time2 - Time1) + " Ms.")
 
Else
  MessageRequester("StringBuilder Résultat...", "Erreur, Le StringBuilder n'a pas put être initialisé !", 16)
 
EndIf

Re: Fast string

Posted: Fri Aug 11, 2017 11:35 am
by marcoagpinto
Fred!!!!

Please implement this:
The easy solution would be to add an option to the PureBasic compiler "x Use fast strings (more RAM needed)"