Page 1 of 1

passing big string to procedures

Posted: Thu Jun 06, 2013 3:30 pm
by spacewalker
Hello,

I am new to PB and I have a question about passing a (big) string to a procedure:

As far as I understood it, strings are not passed ByRef, so this means that a string is copied when it is passed to a procedure?
So if I have a big string and pass it to a procedure - maybe several times - then it will cost much memory since the string is copied...?

Code: Select all

;Pseudo code;
BigString = ReadBigtextfile_to_String()  ;read 100MB textfile into string variable

MyProc1 (BigString)   ;will this copy 100MB to MyProc1 ?
MyProc2 (BigString)   ;will this copy again 100MB to MyProc2 ?

procedure myProc1 (MyString.s)
;do something with myString.s
endprocedure

procedure myProc2 (MyString.s)
;do something with myString.s
endprocedure

Thanks

Re: passing big string to procedures

Posted: Thu Jun 06, 2013 3:47 pm
by skywalk
You can use:
Global.s Big$
procedure myProc1 ()
;do something with Big$
endprocedure

or

Put the big string in a structure:
Structure myStruc
Big$
endstructure
Global someStruc.myStruc

procedure myProc1 (*ptr.myStruc)
;do something with *ptr\Big$
endprocedure

Re: passing big string to procedures

Posted: Thu Jun 06, 2013 3:54 pm
by luis
spacewalker wrote: As far as I understood it, strings are not passed ByRef, so this means that a string is copied when it is passed to a procedure?
Yes.
spacewalker wrote: So if I have a big string and pass it to a procedure - maybe several times - then it will cost much memory since the string is copied...?
It will cost time and the space for one copy.
The copy is destroyed when you left the proc.

To pass by reference you can do it this way:

Code: Select all

Define BigString.String 

BigString\s = "Hello"

Procedure MyProc (*MyString.String)
 Debug Len(*MyString\s) ; up to this point the string was not copied
 
 *MyString\s + " World!" ; now a new string is generated, so a copy takes place.
EndProcedure

Debug BigString\s

MyProc (@BigString)

Debug BigString\s


But as you can see maybe it's a false problem. If you only access the string to read it no copy is performed.
But as soon you start to use string functions on it, on concatenate with another, etc. new strings are created, potentially big or bigger then the source string.

So, the importance of this can be marginal, depends on what you do with the passed string.

Re: passing big string to procedures

Posted: Thu Jun 06, 2013 4:52 pm
by spacewalker
Thank you both for the answers...using a global variable or a structure are good ideas.
But as you can see maybe it's a false problem. If you only access the string to read it no copy is performed.
But as soon you start to use string functions on it, on concatenate with another, etc. new strings are created, potentially big or bigger then the source string.

So, the importance of this can be marginal, depends on what you do with the passed string.
What I want to do with the passed string is to run a FindString () - so it's only a read process...

Re: passing big string to procedures

Posted: Fri Jun 07, 2013 12:11 am
by kenmo
But... won't a new copy be created when it's passed to FindString()?

Re: passing big string to procedures

Posted: Fri Jun 07, 2013 12:26 am
by skywalk
Not if he uses CompareMemoryString() instead.

Re: passing big string to procedures

Posted: Fri Jun 07, 2013 12:39 am
by luis
kenmo wrote:But... won't a new copy be created when it's passed to FindString()?

Code: Select all

a$ = "hello"
FindString(a$, "he") 

Code: Select all

; a$ = "hello"
  MOV    edx,_S1
  LEA    ecx,[v_a$]
  CALL   SYS_FastAllocateStringFree
; FindString(a$, "he") 
  PUSH   dword _S2
  PUSH   dword [v_a$]
  CALL  _PB_FindString@8
From this I can't obviously know what's happening inside findstring but as you can see for both strings their address is pushed on the stack.
So probably the answer is "NO", considering findstring just needs to scan the string.