Re: epoll and nbio
Zombi <[email protected]> Thu, 7 Aug 2003 01:52:35 +0200
| Newsgroups | gmane.comp.java.seda.user |
|---|---|
| Message-ID | <[email protected]> |
I think an implementation of an epoll based nbio will not have a tremendous
performance gainment against the poll based nbio. Mostly because of the too
complex interaction of the java and the native code. I mean when someone want
to read data from a non-blocking socket, he have to :
(populate a SelectSet)
- call SelectSet.select();
then the native code use a lot of JNI, to collect the necessary socket/set
information, issue a system call, then again with a lot of JNI encode the
collected information to the java code
- then the java code need to go through the results and issue a non-blocking
read call (again with JNI) for every socket. This could be a big wastage if
the protocol is simple, and man can predict, for example - that until the
next 64kbytes arrive we don't have to do anything (except to collect the data
:-)
So recently I'm thinking about an alternate, and simpler API instead of NBIO
personally called Java Completion Ports (JCP) (because windows has a very
similar API for this :) and concluded to the following draft:
interface CompletionPort {
public void start();
public void stop();
public Handler register(NonblockingSocket);
public void unregister(Handler);
}
interface SocketHandler {
void enqueRead( Request );
void enqueWrite( Request );
}
abstract class Request {
byte[] buffer;
int current_offset;
int call_requestFinished_after_x_bytes_readed = 0;
public abstract boolean requestFinished();
}
I hope it's simple enough ;-) (at least for me :)
And the usage of this API ( for a very silly protocol ;-)
NonblockingSocket socket = .....
CompletionPort cp = ...
cp.start();
Handler handler = cp.register(socket);
handler.enqueRead( new Request(4096) {
public boolean requestFinished() {
System.out.println("hello world ... we have "+getCurrentOffset()+" bytes");
for (int i=0;i<getCurrentOffset();i++) {
if (buffer[i]==0) {
handler.enqueWrite( new DummyRequest( buffer ));
return true;
}
}
if (getCurrentOffset()==4096) {
setCurrentOffset(0);
}
return false;
}
}
(actually it will wait for a #0 byte, and then send back the 4k buffer, as I
said, it's a very silly program :)
And now the gory details:
- the CompletionPort's start method start a new event dispatch thread which
do the followings:
while (<stop not called>) {
- do the necessary house keeping for the newly (un)registered sockets
- call the big native "dispatchEvents" method
- call the select/poll/epoll/kqueue/... sysfunction to gather readiness
events
- for every event check that there is an extant Request, and if present
call read/write (socket, request.buffer, request.current_offset )
- check that the buffer has more byte than
"request.call_requestFinished_after_x_bytes_readed" then call
request.requestFinished()
}
And that's all ... :-) (I hope:-)
Pros and cons of this API:
+ simpler API - you don't have to care about the necessary bookkeeping, and
with the a synchronization issues, you just request the data to send/receive,
and declare to what to do after.
+ more portable - win32 has the necessary functions, so I'm sure that it will
be a lot easier to port JCP to windows than the porting of NBIO to windows.
And with this API we do not have to emulate a "select"-style event-collecting
interface - which proved to not so scaleable, and performant.
+ better performance - because of the reduced number of JNI, and a possible
OS-friendlyness :)
- mostly speculations, currently not exists :)
- currently no way to cancel a request - however i'm not sure that it's
necessary. In my practice, I happily lived without it :-)
Uhhh ... that's all ... :)
What do you think about ? Is it worth implement it?
Or am I missing something important?
bye
Zsombor
2003. július 31. 11.41 dátummal J. Robert von Behren ezt írta:
> Jared -
>
> I took a look at this several months ago, and ran into a couple of
> problems. Here is what I remember of the situation:
>
> * Make sure you use the epoll system call interface, rather than
> /dev/epoll, as that is what the kernel developers seem to have settled on.
>
> * There is a fairly fundamental mismatch between the level-triggered
> nature of the NBIO code (both in nbio.c) and epoll's edge-triggered
> semantics. This was the reason I decided to scrap the port when I first
> undertook it.
>
> * Fortunately, epoll now also supports level-triggered semantics, which
> are essentially identical to the old /dev/poll. With this, the port should
> be very straightforward - probably a matter of just replacing the various
> /dev/poll calls with their newer epoll equivalents. Just a guess, but this
> is probably no more than a couple days work, if that.
>
> At this point, I don't have any need for an epoll-enabled SEDA myself, so
> I'm not planning to work on this. I'd be happy to answer questions if you
> need some help getting started, though.
>
> Best,
>
> -Rob von Behren
>
>
>
> On Thu, 31 Jul 2003 17:25:26 -0700
>
> "jared allen" <[email protected]> wrote:
> > Has anyone implemented a version of NBIO that uses /dev/epoll instead
> > of the standard poll and /dev/poll device drivers?
> > This is very important to the project I_m working and if anyone knows of
> > other projects that use NBIO that may have done this I_d love to know.
> > Also if anyone is interested in collaborating on a /dev/epoll
> > implementation would be great.
> >
> > Does anyone know what the JDK 1.4.1 and 1.4.2 nio use for polling?
> >
> > Thanks.
> > Jared Allen
>
-------------------------------------------------------
This SF.Net email sponsored by: Free pre-built ASP.NET sites including
Data Reports, E-commerce, Portals, and Forums are available now.
Download today and enter to win an XBOX or Visual Studio .NET.
http://aspnet.click-url.com/go/psa00100003ave/direct;at.aspnet_072303_01/01