Dear GPC Users,
I use long strings to pass numerical data into and out of a shared library I compile from Pascal. Right now, I generate a long string of numbers like this.
program string_demo;
var long_string:string(100000); i:integer;
begin long_string:=''; for i:=1 to 10000 do writestr(long_string,long_string,i:1,' '); end.
Clearly, this is inefficient. It takes 200 ms on my machine. If I use an array of characters instead of a string, and append each new entry to the array, execution time drops to 10 ms.
I can't see a way of using GPC's writestr, concat, or trim functions to accelerate my string generation. I can't alter the long_string.length field directly. If I could fill up the string with spaces first, I could use the string as an array, then trim the spaces off the end. But filling up the string with spaces requires multiple calls to writestr, so I'm back where I started.
It seems to me that I'm missing an obvious solution to my problem, and I thought you might point it out to me.
Yours, Kevan
Kevan Hashemi a écrit :
Dear GPC Users,
I use long strings to pass numerical data into and out of a shared library I compile from Pascal. Right now, I generate a long string of numbers like this.
program string_demo;
var long_string:string(100000); i:integer;
begin long_string:=''; for i:=1 to 10000 do writestr(long_string,long_string,i:1,' '); end.
Clearly, this is inefficient. It takes 200 ms on my machine. If I use an array of characters instead of a string, and append each new entry to the array, execution time drops to 10 ms.
I can't see a way of using GPC's writestr, concat, or trim functions to accelerate my string generation. I can't alter the long_string.length field directly.
SetLength(long_string, 999999).
If I could fill up the string with spaces first, I could
use the string as an array, then trim the spaces off the end. But filling up the string with spaces requires multiple calls to writestr, so I'm back where I started.
It seems to me that I'm missing an obvious solution to my problem, and I thought you might point it out to me.
Maurice
I get a factor of 30 decrease in execution time while making a string out of 10,000 integers when using the following routine to append to append each new interger string to the existing string.
procedure string_append(var s,p:string);
var i,num_to_add,old_length:integer; begin old_length:=length(s); if (s.capacity-old_length<length(p)) then begin num_to_add:=s.capacity-old_length; setlength(s,s.capacity); end else begin num_to_add:=length(p); setlength(s,old_length+length(p)); end; for i:=1 to num_to_add do s[old_length+i]:=p[i]; end;
So, SetLength is all I needed.
Yours, Kevan
Kevan Hashemi wrote:
I get a factor of 30 decrease in execution time while making a string out of 10,000 integers when using the following routine to append to append each new interger string to the existing string.
procedure string_append(var s,p:string);
var i,num_to_add,old_length:integer;
begin old_length:=length(s); if (s.capacity-old_length<length(p)) then begin num_to_add:=s.capacity-old_length; setlength(s,s.capacity); end else begin num_to_add:=length(p); setlength(s,old_length+length(p)); end; for i:=1 to num_to_add do s[old_length+i]:=p[i]; end;
So, SetLength is all I needed.
Or simply (this routine is also defined in stringutils.pas which comes which GPC):
procedure AppendStr (var s: String; const Source: String); begin Insert (Source, s, Length (s) + 1) end;
Frank
I see: the Insert routine. That makes my append routine redundant. Thank you for pointing it out. Yours, Kevan
Dear Adriaan,
But why don't you pass the numerical data in binary form ?
The library is interacting with a Tcl interpreter, which deals with strings. I could pass the data in binary format and then translate into a character string for processing in Tcl. But I'd rather pass the string directly.
Now, it seems to me that the SetLength routine is what I'm looking for.
Yours, Kevan