Newsgroups : Borland : borland.public.delphi.internet.winsock : 2005 May : Weird problem with D7/Indy 10
| Subject: | Weird problem with D7/Indy 10 |
| Posted by: | "Adrien Reboisson" (adrien-reboissonatastasedotcom@nospam.com) |
| Date: | 18 May 2005 02:15:10 |
Hi,
I made an application to transfer files over the network with
Indy 10 (v81) and I have a problem with the speed of the
communication between the client and the server.
Before to send a file I write a block of data which will
be used on the peer side to identify the stream. This is
pure ASCII text, just lines separated by #13#10 and terminated
by a double #13#10. Exactly like HTTP.
The problem I have is for receiving data. When I tested my
application to send a lot of small files, I remarked that it was
very slow (about 1 or 2 files per seconds), despite our 1
gigabit network (obviously when I done my first tests it was all
on "localhost" and all was perfert - about 10 or 20 files
transfered per seconds). Even if I transfer bigger files, the
speed remains identical. As a result, I thought my problem came
from the headers sent by the client and received by the server
just before the stream itself.
I traced my program and discover that the bottleneck came from
ReadLn(). My messages looks like this :
<[Kind of message] @[Transaction ID]>
FistProperty: FirstValue [CrLf]
SecondProperty: SecondValue [CrLf]
ThirdProperty: Thirdvalue [CrLf]
(...)
PropertyN: ValueN [CrLf]
[CrLf]
[CrLf]
In the server, I read (with ReadLn) the first line in the
OnExecute event handler. According by the kind of message
decoded, a specific function is called to extract the content of
the message until the double crLf is read. I measured the time
it took to read each line of the content and I discovered that
the first line (here, "Fist property...") needs about 200ms to
be read. The others lines takes about 0 ms to be read. Why ? As
the function to read the body of the message is called I suppose
the entire message (or a big part of it, at least) is already in
the buffer. Then, why it takes 200 ms ?
I've done a small test: I made a client and a server (just
dropped a TIdTCPClient and a TIdTCPServer on two blank projects),
included and used the functions to read my messages and measured
the time taken by the server to read the message content sent by
the server.
On the client side, I have something like this :
procedure TForm1.Button1Click(Sender: TObject);
var
M: TThMessage;
begin
//connects the client, if not connected
if not RLClient.Connected then
RLClient.Connect;
//fill the message with some stupid values
M.Header.StatusMessage := 'Imperial Message';
AddMessagePartAsString(M, 'Luke', 'zzzzzzzzzzzzzzzzzz');
AddMessagePartAsString(M, '...', 'zzzzzzzzzzzzzzzzzz');
AddMessagePartAsString(M, 'I', 'zzzzzzzzzzzzzzzzzz');
AddMessagePartAsString(M, 'am', 'zzzzzzzzzzzzzzzzzz');
AddMessagePartAsString(M, 'your', 'zzzzzzzzzzzzzzzzzz');
AddMessagePartAsString(M, 'father...', 'zzzzzzzzzzzzzzzzzz');
AddMessagePartAsString(M, 'Nooooooooo', 'zzzzzzzzzzzzzzzzzz');
AddMessagePartAsString(M, 'ooooooo.......', 'zzzzzzzzzzzzzzzzzz');
//Then write the message using WriteLn()
WriteQueryMessage(RLClient.IOHandler, M);
end;
If I call this function from inside a timer with a 500ms interval
set, the measured times on the server side for 18 packets sent
are (in milliseconds) :
109, 172, 186, 186, 187, 124, 186, 109, 202, 93, 109, 108, 108,
124, 124, 124, 124, 156
I tested to disconnect the socket at the end of the function and
the results changed drastically :
[...]
//Then write the message using WriteLn()
WriteQueryMessage(RLClient.IOHandler, M);
RLClient.Disconnect;
end;
0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 16
Okay. Better. But why ??
I'm a little bit puzzled. I want absolutely to decrease the time
taken for the encoding/decoding messages headers, but how can I
do it ?? Why in my tests, if I disconnect the socket after having sent the message they are read faster on the server side ?
Any hint _greatly_ appreciated.
Best regards - and sorry for this loooong message with my baaad
english :-)
A.R.