zaphoyd / websocketpp

C++ websocket client/server library
http://www.zaphoyd.com/websocketpp
Other
6.88k stars 1.95k forks source link

Need vectored read and write support of payload. #206

Open RavikumarTulugu opened 11 years ago

RavikumarTulugu commented 11 years ago

Need vectored send and receive of websocket frames, right now the message is received in the form of a continuous string, this results in reallocation and unnecessary copies and movements of data which affects performance. it would be good if the websocket frames can be send and received as a sequence of buffers. The application can choose to assemble the data or use it as it is.

RavikumarTulugu commented 11 years ago

any comments on this will be appreciated whether this is in your plan or not. Thanks.

zaphoyd commented 11 years ago

Regarding Vectored Send: WebSocket++ core and both the iostream and ASIO transports already support vectored sends. This is presently used to send header, extension data, payload data without copying them in line. As such once the application copies data into a WebSocket++ message buffer there are no additional copies within the library before it is written to the wire. WebSocket++ allows applications to generate a message buffer before calling send. This gives the application an opportunity to write/append data directly into the final payload buffer at its leisure. There is presently no interface to expose a vectored payload to the application though. Doing so could offer additional flexibility but would introduce some other issues that need to be thought through carefully. In particular:

In order to prepare messages for writing on the wire, WebSocket++ needs to alter the message payload itself for various reasons. The most common include masking and/or compressing the data. For this reason I cannot easily create a universal copy free interface that accepts a sequence of const buffers. A sequence of non-const buffers turns out to be significantly more dangerous (the library is essentially writing to space that it doesn't control with no guarantees about thread safety, etc). It also makes deduplication/prepared message send more difficult (this would be sending a single message to multiple destinations with shared masking/compression/framing).

Regarding Vectored Receive: WebSocket++ 0.3 currently provides a nearly copy free receive interface. When a message header is received, the exact payload size is known up front, a buffer is allocated for the entire message at once and then is read into that buffer with no copy/reallocates. A pointer to that buffer is then passed directly to the application via on_message again with no copying. The end application is free to do whatever it likes with that buffer for as long as it likes without affecting the library itself. The only copying that is done is from a very small network receive/unmasking/decompression scratch space.

In general: WebSocket++ supports pluggable message buffer policies. There will be reference implementations with good defaults for the common use cases. This doesn't preclude additional specialized policies for other types of message buffers for more niche use cases.

The current default message buffer policy in 0.3 is tuned for correctness, robustness, memory usage efficiency, and thread safety. It is not tuned for speed. I absolutely intend to provide alternate ones with different tradeoffs. I would see vectored send as one performance boosting tradeoff option among many. Others including pools of pre-allocated buffers that are recycled, prepared/deduplicated messaging, stack allocators for connections, etc.

Exactly which of these options will get implemented in the bundled message buffer policies will depend on the use cases I see as most common as well as on real world profiling data that shows that there is indeed a bottleneck and that the given option improves it. If you have a specific use case in mind and especially if you have profiling data that demonstrates a measurable bottleneck I'd love to hear it and incorporate that feedback into better message buffer policies.

I would be interested in hearing any more detailed thoughts you might have on what benefits you think vectored receives would provide and what interfaces you would find useful for vectored sends.

RavikumarTulugu commented 11 years ago

In most of the cases the buffer or the websocket payload needs to be forwarded to other process or application, it is in this context i was asking for the support of vectored write and read. The use case in my scenario was to avoid the copy of payload from the message to the application buffer and then again the application buffer needs to be written to kernel. so there are 2 copies of data 1 from the websocket payload buffer to the application buffer and then from application buffer to kernel space. I was seeing if we can tell message buffer to use a user provided memory pointer for storing the payload , this can come from a shared memory region. this way we can effectively reduce the number of times data gets copied. effectively if we can plugin an allocator for message buffers then the problem is solved.

zaphoyd commented 11 years ago

In short, yes, the message buffer system will be entirely pluggable for that reason. I haven't finalized the internal interfaces for the message buffers yet, so any feedback on what sort of custom message buffer policy features might be useful to you would be helpful.

That said, do feel free to use the message buffer you get from WebSocket++ directly in your application. In many cases there is no need to copy from the message buffer to an application buffer. You can get a non-const reference to the underlying string as well with get_raw_payload() if you want to edit a received message in place.