jsr340-experts@servlet-spec.java.net

[jsr340-experts] Re: Do we really need async IO

From: Greg Wilkins <gregw_at_intalio.com>
Date: Thu, 8 Mar 2012 16:45:35 +1100

On 7 March 2012 18:47, Remy Maucherat <rmaucher_at_redhat.com> wrote:

> We have a big (unique) opportunity to provide an API which would do the
> full thing efficiently, let's not waste it.

Which is exactly why we have to consider a range of possibilities. I
think it is worthwhile to consider an API based on the JDK7 style, but
I accept that if it cannot be made efficient, then there is not point.


> I don't understand how it can be efficient, although I get the idea it
> can provide most of the functionality.
>
> Besides encouraging using temp files,

The write file API is there for static content not temp files. The
idea is that the container can very efficiently use direct buffers to
write a memory mapped file, so this has the potential to be even more
efficient.


The read file API may encourage temp buffers. So let's add a
    public <A> void read(ByteBuffer buffer, CompletionHandler<Boolean,
AsyncContext> handler)
    {
    }
that reads content into the buffer until it is full or EOF and then
calls back the handler.


> write(ByteBuffer) has to wait for the servlet to return, then call the
> completion handler, before the servlet can write again. That's a large
> lag between each write.

Not at all. As soon as you have an AsyncContext you can call write, so
immediately after startAsync. However as we'd want this for upgrade
as well, perhaps the methods should be on request/response or some
other entity that works for both. The key think is that they can be
called as soon as the async mode is entered (via startAsync or
upgrade).

Once the write is complete, I don't see why the callback to the
completion handler is any faster/slow than the callback to canWrite.
  The mechanism will be similar except the semantic is simpler.

With the current proposal, the container has to detect a write that
did not full write all the bytes passed and schedule a callback when
the connection is again writeable. The application has to notice that
not all bytes were written and give up the thread, remembering the
unwritten bytes, and wait for the callback. Once the callback
occurs, the app can write the remembered unwritten bytes and if that
completes can go onto the next write.

With my proposal, the app writes the bytes and gives up the thread (or
does something else). Once the container has written all the bytes, it
calls back the application, which does the next write.

For large content, you could expect many blocks and canwrite
callbacks, so the current proposal would require a lot more call backs
than my proposal.


> On the async API we propose, it is possible the
> servlet can continue writing, thus avoiding a costly round trip to the
> container.

No, the servlet has to check each write to see if all the passed bytes
were written, and if not, then give up the thread and wait for the
canWrite callback.