String command

Started by _PJ_, September 01, 2018, 22:08:03

Previous topic - Next topic

_PJ_

Is there an equivalent for the B3d/B+ String command?

How efficient is

Funciton DoStringRep:String(AString:String,Rep:Int)
int a:Int
while a<Rep
  AString+:Astring
  a:+1
next
return AString
End Funciton

Henri

#1
Blitzmax equivalent would be:

Code (blitzmax) Select

Local start:Int = MilliSecs()
DoStringRep("Hello", 5000)
Print "DoStringRep took " + (MilliSecs()-start) + " ms. Memory consumption was " + GCCollect() + " bytes."

Function DoStringRep:String(AString:String,Rep:Int)

Local a:Int, s:String = AString

While a < Rep
AString:+ s
a:+1

Print a
Wend

Return AString
EndFunction


You wouldn't want to be adding a string to itself, as this would cause a GC-error pretty soon. So I've added a tmp string to avoid this.

-Henri
- Got 01100011 problems, but the bit ain't 00000001

Derron

#2
You might consider using Brucey's StringBuffer module if you do that regularily:
https://github.com/maxmods/bah.mod/tree/master/stringbuilder.mod
(in my Dig-Framework it is still called StringBuffer but it got renamed to StringBuilder some time ago)

Code (BlitzMax) Select

Superstrict
Import "../Dig.git/external/stringbuffer.mod/stringbuffer.bmx"

GCCollect()
Local start:Int = MilliSecs()
DoStringRep("Hello", 10000)
Print "DoStringRep took " + (MilliSecs()-start) + " ms. Memory consumption was " + GCCollect() + " bytes."

GCCollect()
start = Millisecs()
DoStringRep2("Hello", 10000)
Print "DoStringRep2 took " + (MilliSecs()-start) + " ms. Memory consumption was " + GCCollect() + " bytes."

GCCollect()
start = Millisecs()
DoStringRep3("Hello", 10000)
Print "DoStringRep3 took " + (MilliSecs()-start) + " ms. Memory consumption was " + GCCollect() + " bytes."


Function DoStringRep3:String(AString:String, Rep:Int)
Local sb:TStringBuffer = TStringBuffer.Create(AString)
Local AObj:TStringBuffer = TStringBuffer.Create(AString)
For local a:int = 0 to Rep
sb.AppendObject(AObj)
Next
return sb.ToString()
End Function


Function DoStringRep2:String(AString:String, Rep:Int)
Local sb:TStringBuffer = TStringBuffer.Create(AString)
For local a:int = 0 to Rep
sb.Append(AString)
Next
return sb.ToString()
End Function


Function DoStringRep:String(AString:String,Rep:Int)

        Local a:Int, s:String = AString

        While a < Rep
                AString:+ s
                a:+1

'                Print a
        Wend

        Return AString
EndFunction



./bmk makeapp -t console -quick -r -x "/home/ronny/Arbeit/Programmieren/Projekte/Testcodes/stringrep.bmx"
[ 92%] Processing:stringrep.bmx
[ 98%] Compiling:stringrep.bmx.console.release.linux.x86.s
flat assembler  version 1.68  (32768 kilobytes memory)
3 passes, 4082 bytes.
[100%] Linking:stringrep
Executing:stringrep
DoStringRep took 100 ms. Memory consumption was 899810 bytes.
DoStringRep2 took 1 ms. Memory consumption was 100032 bytes.
DoStringRep3 took 0 ms. Memory consumption was 100044 bytes.


If you increased to eg 50.000 calls, then time difference will be even heavier.


Edit: when compiled with NG I got a memory consumption of 0 bytes (which is surely "flawed") and the original approach of Henri took longer:

DoStringRep took 335 ms. Memory consumption was 0 bytes.
DoStringRep2 took 1 ms. Memory consumption was 0 bytes.
DoStringRep3 took 1 ms. Memory consumption was 0 bytes.


Thought GCC will optimize this stuff... hmm.

bye
Ron

_PJ_

Your attempt to time the functionality is a bad approach. Hence the inconsistency.


You need to time the overall repetition of the function a significant number of times (making sure to time only the raw functionality, not the feedback and other assignments)

Take mean of the value and this is a data point.

Then repeat the above a numebr of times. These are additional data points.

Now take THIS mean, also note the deviation and outliers, and it will be a more meaningful statistic

Derron

#4
I would suggest not to teach the teachers.

We are aware that function calls _might_ have overhead (might as well get inlined by the compiler and so on). Also multiple runs will average out spikes. Also cutting out the worst X and best X of all tests might help.

_BUT_
If you run a code which leads to eg. 5 seconds run time - and the other one finishes in 2 milliseconds I would skip running it 1000 times to average out spikes/hickups because of bad OS timing schedulers.

_AND_
Memory consumption stays the same as it is based on the objects (and their individual memory consumption) it needs to create during appending stuff. It won't change no matter how often you execute the functions.

@ inconsistency
The execution times differ as all functions do different stuff:
- string + string (which creates a new string everytime, garbaging the old one, needing memory allocation ..)
- stringbuffer + string
- stringbuffer + stringbuffer


bye
Ron