Bela Ban created JGRP-2110:
------------------------------
Summary: Transport: revisit buffers and threading
Key: JGRP-2110
URL:
https://issues.jboss.org/browse/JGRP-2110
Project: JGroups
Issue Type: Task
Reporter: Bela Ban
Assignee: Bela Ban
Fix For: 4.0
(Concerns only the receiver side)
h4. Parsing
Currently, parsing is done on the thread which received the message (or message batch) and
then the message is passed on to the thread pool. One could argue that the parsing should
be done on the thread from the thread pool, and the receiver thread should only receive
fill the buffer and pass it to the thread pool immediately, without doing any parsing, as
this might slow it down.
This actually used to be the model which JGroups used, but I abandoned it because (1)
performance (IspnPerfTest and UPerf) was the same and (2) we could get rid of a buffer
copy (more on this below).
h4. Buffers
* UDP has a fixed buffer of 65K. A datagram packet is read into this buffer and then
parsed and passed to the thread pool, allowing the buffer to be reused for the next
message.
* TCP: each connection has a buffer which grows according to the length sent in the header
of a message. This buffer doesn't need to be copied when passed up the stack, until
receive() returns
* TCP_NIO2: each connection also has a buffer which is reused after receive(), but if the
read is not complete, is copied.
h4. Approaches
# The receiver thread parses the buffer into a message and passes the message to the
thread pool for processing. This requires memory allocation (the new message and its
payload buffer). This is the current approach. Parsing the buffer into a message might
slow things down as message creation requires memory allocation.
# The receiver thread passes the buffer on to the thread pool where it is parsed. The
advantage is that the receiver thread is immediately ready to receive new messages. The
disadvantage is that this is 1x memory allocation for the message (as above), although
done on a seperate thread, plus 1x memory allocation for copying of the buffer to reuse
the original buffer (where necessary, depending on the transport). This was the old way of
handling incoming messages.
# UDP: it is possible for the socket receive() method to be called by multiple threads. We
could therefore create multiple receiver threads in UDP, to speed things up.
# To prevent memory allocation of the approaches above, we could create a buffer pool. The
receiver thread grabs a buffer from the pool (the pool creates a new one when empty?) and
fills it with the socket's receive() method, then passes the buffer to the thread pool
for processing. If the message's payload buffer points to the original buffer (from
the buffer pool), the thread from the thread pool returns the buffer to the buffer pool as
soon as the {{receive()}} callback returns, otherwise it returns it as soon as the message
has been parsed.
h4. Goals
Prototype approaches 2, 3 and 4 and benchmark them against each other, using UPerf and
IspnPerfTest.
--
This message was sent by Atlassian JIRA
(v6.4.11#64026)