Hello!

> Have a look at TTWSChatForm.CliWSocketDataAvailable in TWSChat1.pas
> source
> file. There is a RcvBuf which is a stically allocated array of char (you
> can
> make it dynamically allocated) where data is received and the end of what 
> has already been received. RcvLen variable keep track of how many bytes
> have
> been received so far. In that sample we know to have received all data
> (and
> maybe more) when we find a #10 in the data. This character mark the end
> of
> message (or end of line if you prefer). Then data is processed. What is 
> after #10 is moved in front of buffer and RcvLen is adjusted accordingly.
 
Yes, and you used similiar idea in TPop3Cli. Although it's simple to code,
it's far from being optimal when you're about to receive short (40-80 chars)
lines into medium/large sized buffer (say, 8kB) from relatively fast source
- let's say we've received 8118 bytes, and let's assume that there's 99
lines, each consisting of 80 chars and 2-byte line end marker (cr/lf) -we of
course don't know line lengths and amount of lines beforehand. Now let's
fetch it. How does it work:

- find cr/lf, traverse 81 bytes, stop at 81
- copy that 80 bytes to parser's buffer (or something like that)
- move 8036 bytes of buffer, counting from 83 byte, back to the front
- find cr/lf, traverse 81 bytes, stop at 81
- copy that 80 bytes to parser's buffer (or something like that)
- move 7954 bytes of buffer, counting from 83 byte, back to the front
[...]
- find cr/lf, traverse 81 bytes, stop at 81
- copy that 80 bytes to parser's buffer (or something like that)
- move 82 bytes of buffer, counting from 83 byte, back to the front
- find cr/lf, traverse 81 bytes, stop at 81
- copy that 80 bytes to parser's buffer (or something like that)
- note that we've hit buffer boundary, so exit.

If we'll count well how many bytes were actually moved, we see that this
solution is FAR from being optimal (for those who don't want/can't count it:
we'll move 405702 bytes, or 396 kBytes). That superfluous memory moving
is not the only bottleneck - here we have constant cache invalidation and
cache misses, so if you change algorithm to better one (similiar to one
below), you may get enormous speedups.

That's the point of code I've sent you recently (btw: discard that "if
FBlockme=..." line, I just forgot to delete it).

And the algorithm is pretty simple, but more difficult to code:

- set buffer cursor's current position as "starting position"
- find cr/lf
- if cursor hit buffer boundary (and cr/lf were not found), move everything
  from "starting position" to the end of buffer into the front of buffer,
  remember how many bytes were moved (as we want to receive new data after
  old, and we don't want old data to be deleted), and exit
- otherwise, if cr/lf was found, copy data from "starting position" to byte
  before cr/lf to parser's buffer, and move cursor past cr/lf.

This algorithm, in ours test case, has moved 7920 bytes (almost 8kB) bytes,
cache wasn't dirtied, and if parser code was simple (like a call to
TBufferedFileStream.Write), then buffer receiving could be done with speed
at least near to optimal. And definitely it is NOT TRUE that it makes
difference on just low-end cpu's. 

-- 
Piotr "Hellrayzer" Dalek
[EMAIL PROTECTED]

----------------------------------------------------------------------
INTERIA.PL | Kliknij po wiecej >>> http://link.interia.pl/f18c1

-- 
To unsubscribe or change your settings for TWSocket mailing list
please goto http://www.elists.org/mailman/listinfo/twsocket
Visit our website at http://www.overbyte.be

Reply via email to