Re: Functions needed



Thanks you all for your comments.

Here's the final code.
Maybe I'll try the 'state' machine,
which is very easily readable
(what I like when coding).
Seems to be fast as well.

To explain quickly what I'm doing :
- I have a server that gives http adresses
in a xml-encoded form (to be able to parse the adresses) ;
- I have many clients that ask for new http adresses,
connect to the web sites and get the result, and send it
back to the server into a http post where i put the
result in a xml-encoded variable.

Everything looks like it's a big overhead,
especially xml. I could have done my own format,
with (for example)
2 first bytes=length of the whole message,
2 bytes=length of the sub-message
1 byte=type of the sub-message
then the sub-message itself

Without all the overhead I've done.

But I wanted to trace everything, to
know if everything was okay, to make
statistics quickly, to be able to read
the whole traffic easily, and so on.
Then came up this idea : a http-web
server that gives thes adresses in a
xml-encoded form. This way I cant see
with Firefox what adresses I can get :
just connect and ask for a url
like http://localhost:8080/ask/xxx
(Works perfectly by now).
And I wanted to send the results
exactly the same way : I just
had to make my little http page
where I put a <form method="post" ...> </form>
and a file input, and a send button.
This whay I could send whatever file
I wanted to my server, and deeply test it
(send crappy files, huge files and
so on).
Here were born 'XMLEncode' and 'XMLDecode'.

After two months of (personal) hard work
(from 18h00 'till 1am :DD) everything works fine.
My server is perfectly stable. So are my clients.

But the cpu time was 100% for the clients
and 100% for the server.
The main problem was (is :^C ) optimization.
For the server, the problem was simple to
solve : when the server gets a response,
sometimes the file is huge, and it's three
times its size in the xml-encoded form.
I created a xml component and downloaded
the result into it. It took ages.
So I 'cut' by hand the result into another
var and use the conversion routine
(XMLDecode) with this var. The rest is
piece of cake (create a xml component
and download what's left into it
(around 100 bytes length =>
almost instantaneous)). XMLDecode
still takes CPU time but it's very
fast with the new routine and it's
okay for now.
(I'll try the state machine anyway ;-D )

The problem is on the client side.
The client has something like 40 threads
running (it will grow up with time
and bandwidth). When the thread
gets the complete html result (the less
was ~5 Ko, the biggest was ~1 Mo (but
I have to deal with situations where
I'll havebigger results)), it has
to encode the whole thing into
a xml var to be able to post it.
The XMLEncode seems to be fast,
but not enough for big files.
So I've listened to you :
here is the XMLEncode function,
but instead of doing
Result := StrPas(globPData);,
I'll try something like :
allocate only
Result (SetLength(Result, ALength*5));
and work directly on it.

My optimization question is :
is it quicker to use a pointer and to
increment it (
P : PChar then
P := @Result[1] then
Inc(P)
if P^ ...),
or to use an index (
I := 1;
Inc(I);
if P[I] ... )

??

function XMLEncode(const AChaine:PChar; const ALength:Integer):String;
var
I : Integer;
J : Integer;
S : PChar;
B : Byte;
begin
I := (ALength*5)+1;
if globTmpSize<I then
begin
globTmpSize := I;
globPData := GlobalReAllocPtr(globPData, I, GMEM_MOVEABLE);
end;

S := AChaine;
I := 0;
J := 0;
while I<ALength do
begin
B := Byte(S[I]);
if (B<40) or (B>122) or (B in [60,61,62,63]) then
begin
StrPCopy(@globPData[J], globTabHexChars[B]);
Inc(J, Length(globTabHexChars[B]));
end
else
begin
globPData[J] := S[I];
Inc(J);
end;
Inc(I);
end;
globPData[J] := #0;
Result := StrPas(globPData);
end;


procedure XMLDecode(var AChaine:String);
var
I, J, K : Integer;
begin
I := 1;
J := 1;
K := Length(AChaine);
while J<=K do
begin
if AChaine[J]='&' then
begin
AChaine[I] := Char(StrToInt('$'+AChaine[J+2]+AChaine[J+3]));
Inc(J,5);
end
else
begin
AChaine[I] := AChaine[J];
Inc(J);
end;
Inc(I);
end;
SetLength(AChaine,I-1);
end;


.