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

Reply via email to