XTP, JDBC and NIO: It’s a Dirty Job, But Someone’s Got To Do It

xtp-new-and-improved.jpgSo, I was thinking more about the topics in the last post and was wondering about how to go about the transformation of the JDBC implementation and what kind of cooperation would be required with the various driver implementations to pull it off. Originally, my thought would be to make the non-blocking transform at the boundary of the JDBC API, itself. The idea being that there would have to perhaps unpleasant details I’d have to deal with at the driver implementation level and I’d likely need the cooperation of the vendor in some fashion to carry it out.
Boy was I wrong. After playing with a few examples, I found that I can have this framework operate at the java.net.Socket layer and by doing so, I can completely bypass any cooperation requirement with the JDBC implementation, itself, and simply coopt any JDBC implementation as part of the continuation chain – i.e. the JDBC driver is treated just like the application code would be. This means that the transformation is actually even more powerful than I originally suspected and means I can transform any existing blocking code – within reason, of course – into a completely threadless, non-blocking form.
The upshot is that I can now put the X in XTP without even making anyone write a single line of code.

5 thoughts on “XTP, JDBC and NIO: It’s a Dirty Job, But Someone’s Got To Do It

  1. Hi Hal,
    This project looks amazing, is the source code available? I tried the link to the 3rd space project on Google Code, but got a permission denied error.

  2. Unfortunately, I had to make the decision to take it closed source due to a variety of different constraints. Thus, I deleted the Google project and moved it to a private SVN repository host.
    Seems as though one is never as unencumbered as one would imagine…

  3. The approach sounds similar to how tomcat and glassfish use NIO under hood. Is that an accurate description?

  4. I assume you’re referring to the Asynchronous Request Processing in Grizzly. I’m not too familiar with the stuff in Glassfish, so you’ll have to forgive my ignorance. From what I can tell, it’s merely an “interruptable” model which is driven by events. The read and write are still blocking and – at least from what I can tell – the calling code will still block under a variety of conditions – perhaps I’m just confused as to the implementation and some actual handling of the blocking nature of the ServletInput/OutputStream is handled with a RuntimeException or something cutting through the stack and a side agreement with the framework as to what conditions that can happen.
    However, this is not the model I’m proposing.
    As I talked about in the previous post, the omnipresent model is to make the system blocking during the execution of the application code. I believe this is still the case for the Glassfish model, but I assume they switch back to non-blocking mode while the servlet code is no longer running.
    The system I’m describing provides the complete illusion that the blocking APIs are operating just as everyone thought, but the execution of the code using these APIs – i.e. the Servlet, in this case – can be completely interrupted without a Java thread keeping the execution state.
    For example, let’s take the simple example of a transformation servlet. The idea being that we want to do some streaming transformation on the input stream and send the result back to the client. Let’s further stipulate that this is a stream of 400 megabytes to make it interesting. The client is over a slow connection, and may be doing processing itself.
    So, from the servlet’s POV, the code can block when reading bytes from the input stream and may well block when writing to the output stream. With my transformations, you could simply write the servlet in the straight forward fashion:
    while (true) {
    read = input.read(buf);
    … some txfm
    output.write(buf, 0, read);
    Under the covers, my framework transforms both the blocking read and the blocking write into true NIO, non blocking calls. So when the client hasn’t placed any bytes on the inbound stream, the Servlet code above would be suspended at the input.read(buf) line. Likewise, if the OS can’t buffer the output seeing as how the client is slow or the network is congested, the servlet code would be suspended on the output.write(buf) line.
    In the Glassfish ARP framework, I believe that there would still be a Java Thread which represents the execution state of that code in either case.
    In my transformations using Prime Mover, the blocking reads and writes are transformed into continuations where by the Java thread is eliminated and there is no stack there at all. So the reads and writes are handled using a standard, fully non blocking NIO channel pattern. When there’s enough bytes to satisfy the read or the socket becomes write ready, the execution of the Servlet code is resumed where things were left off.
    I’d be very interested in finding out that Glassfish has solved this problem, but I don’t think they have done this.
    Also, the thing I realized last night is that I can do this same trick for any blocking API, which in the subject of XTP comes to the JDBC API without changing the JDBC driver code what so ever. So, any application code calling the blocking JDBC API and even the JDBC driver code itself is suspended when the socket reads and writes occur and everything now happens with an NIO event driver, rather than having a Java thread containing the execution state blocking on the read/write from/to the Database connection.

  5. Damn, looks like I’ll have to implement it myself, then.
    BTW have you seen Paul Tyma’s slides here?
    Interesting stuff, looks like on modern systems NIO isn’t necessarily the panacea that people think, and in many cases may actually reduce throughput. I haven’t tried to reproduce his results, but I’ve seen similar reports in a couple of places.
    And no, it’s not just sour grapes because I can’t get the source :-)

Comments are closed.