Task #1265
closedMulti-buffer send operation on transport
100%
Description
boost::asio support non-consecutive memory blocks to be used within the same send operation. This feature is necessary to support multiple LocalControlHeaders for the same Interest/Data.
As part of this issue is changing logic of memory management for LocalControlHeader. It is no longer is an extension of Interest/Data wire, but is independent piece that is stored in a separate memory buffer and is prepended to the Interest/Data wire during send operation.
Updated by Alex Afanasyev over 11 years ago
- Project changed from NFD to ndn-cxx
- Assignee set to Alex Afanasyev
- Priority changed from Normal to High
Updated by Davide Pesavento over 11 years ago
Would be nice to have scatter/gather on the receive side too. I was trying to implement it inside StreamFace today, using a boost::circular_buffer, but I got stuck because Block constructor seems to require a single continuous memory buffer. It shouldn't be hard to do and it could save ourselves at least one memory copy operation in the receive path.
Updated by Alex Afanasyev over 11 years ago
It could be nice, but I don't clearly see real value. The copy operation in the receive is really an artifact that I currently have and can be (partially) easily avoided even without circular buffer: for each new read, just allocate maximum packet size buffer and read, and then create Block from the buffer directly (or multiple blocks from the same buffer, if it happened to be the case).
In any case, I checked and it seems that circular_buffer is only in boost 1.55...
Updated by Alex Afanasyev over 11 years ago
- Status changed from New to Code review
I made a very simple implementation, just allowing two unrelated Block's to be passed to transport's send operation. Similar thing could be implemented inside NFD inside StreamFace.
Updated by Junxiao Shi over 11 years ago
for each new read, just allocate maximum packet size buffer and read, and then create Block from the buffer directly (or multiple blocks from the same buffer, if it happened to be the case).
This solution will not work.
Suppose maximum block size is 8 octets, and a letter indicates the beginning of a packet:
- Incoming stream is
A1234B123C12 - First read operation receives
A1234B12, and delivers blockA1234. - Second read operation receives
3C12. It must combineB12left over from first read operation with3to deliver a continuous block.
There is a trick to avoid copy and receive exact blocks:
- Read 10 octets.
This is guaranteed to contain INTEREST-TYPE | DATA-TYPE and TLV-LENGTH.
This is also guaranteed not to contain more than one block, because the smallest possible block is .... which is 10 octets. - Based on TLV-LENGTH, allocate a buffer enough for the whole block including the first 10 octets, write the first 10 octets into the buffer, and receive subsequent octets.
This trick trades an extra read(2) syscall for a memory copy operation of a whole block. Benchmark is needed to compare the overhead.
Updated by Alex Afanasyev over 11 years ago
I actually don't want to bother optimizing stream-based faces... Personally, I would prioritize datagram-based faces and optimize them, while having stream-based (TCP) just work.
Updated by Alex Afanasyev over 11 years ago
- Status changed from Code review to Closed
Updated by Davide Pesavento over 11 years ago
Alex Afanasyev wrote:
In any case, I checked and it seems that circular_buffer is only in boost 1.55...
No, it first appeared in boost 1.35
http://www.boost.org/doc/libs/1_55_0/doc/html/circular_buffer/release.html
Updated by Alex Afanasyev over 11 years ago
oops. I was just changing 1_55_0 to different versions and if the page not there, I assumed it wasn't in the library. In that case, we can investigate this optimization, which in part should be in ndn-cpp-dev (different Block implementation).