Here is a tentative rollout of non-blocking polling for live
connections, assuming everything else (handshaking, authentication &
trailing field stuff) stays blocking. This should save 30-40% of
threads used. If authentication is also nio'd that percentage will rise
to above 50.
1. change all sockets used in fred to use channels. The changes to the
code are minimal (and already done in my local copy) but break
compatibility with jre's older than 1.4.
1.5 (optional) make the FNP and FCP interfaces non-blocking, thus saving
one thread. Again code changes are minimal.
2. After a connection is established on an interface and the
handshake/authentication is complete, change the socket to non-blocking
mode and pass it on to the object doing the select loop.
3. Implement the select loop. It will run in a single thread which is
recommended to have higher priority than the others. The object
representing the select loop will keep track of all open connections
(through connection handlers) and those who are receiving trailing
fields will be marked. The ConnectionHandler object will be augmented
with a flag whether its processing trailing field and with a buffer
holding received data.
The basic operation of this select loop is the following:
3.1. block for any network input on the open connections for a
specified timeout (20-200ms?)
3.2. query those ConnectionHandlers that have been registered as
reading trailing fields, and if any of them have completed their reads
re-register their channels to the selector.
3.3 Read the available data and put it in the buffers of the
appropriate ConnectionHandlers
3.3.a) If the received data contains an "EndMessage", enter the
message parsing code and produce a messageObject. I'm assuming those
messageObjects are afterwards taken care of separate threads.
3.3.b) If the received data contains an "Storable=", mark the
ConnectionHandler as busy, unregister it from the selector and change
the appropriate socket to blocking mode. After that enter the code
that deals with trailing fields in a separate thread.
3.3.c) If neither of those is there, return and process the next
ConnectionHandler.
3.4 Register to the selector any newly opened connections passed
from the interface.
Other than implementing the loop, changes include checking whether a
complete message has been received before running the
ConnectionHandler.run() method. In that method the streams will have to
be backed either by a String or byte[]. No changes are required to the
code that deals with trailing fields because blocking streams work fine
with blocking sockets, except that right before dying the thread that
reads the trailing fields must mark the ConnectionHandler as available
and wakeup() the selector.
All in all, the amount of code changes is not as big as first expected.
If the authors of the current code don't mind being bothered by me
asking questions every so often, the transition can be done in 1-1.5
months. Perhaps even less.
_______________________________________________
devl mailing list
devl at freenetproject.org
http://hawk.freenetproject.org:8080/cgi-bin/mailman/listinfo/devl