|
Boost : |
From: pedro.lamarao_at_[hidden]
Date: 2005-06-13 06:13:19
Maxim Yegorushkin wrote:
> ... And too slow. You have one data copy from kernel into the streambuf,
> and another one from the streambuf to the message object. The same is for
> output: message -> streambuf -> socket. This is unacceptable, at least for
> the kind of software I build.
>
> For example, I had a router which used a TCP binary protocol. Each message
> is prefixed with 4 byte length, so I read the 4 bytes, resized a
> std::vector<char> for the message length, and then read the message into
> the vector. After profiling the router under heavy load it turned out that
> 30% of user time was spent in guess where? In zeroing out memory in
> std::vector<char>::resize(). And you are talking about data copying here...
Considering the protocol of your application has built in methods for
announcing the length of the payload, your requirement is met by the
streambuf::sgetn(char_type*, streamsize) method, for a properly
specialized implementation of the virtual protected xsgetn method.
A streambuf manipulated solely by sgetn and sputn won't ever fill
internal buffers.
By encapsulating your protocol message inside a protocol_message object
with proper operator<< and operator>>, you can receive and send such
objects by directly manipulating the streambuf associated with a stream
through stream::rdbuf().
A proper implementation of xsgetn would would directly call the
networking primitive with the proper parameters, after sanity checking,
taking into account the possibility of there being characters in the
internal buffer, for complete correctness. We'll get a couple of
branches for every call to recv(), so, yeah, we're probably not 100% on
par with C here; but then, we'll only call recv() twice for each object
received anyway.
Also, an implementation of a networking streambuf can implement "no
buffering" semantics set up by a streambuf.pubsetbuf(0, 0) call (like
your typical fstream provides) to absolutely ensure there is no
buffering going on.
So you get operator semantics for free. :-)
And perhaps even a putback area, if there's one provided by this
particular streambuf implementation.
I'll take a note of this use case, though. As soon as documentation is
finished for my last proposal, I'll try and do some benchmarking. How
large are your payloads, usually?
-- Pedro Lamarão
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk