Home > Java > Critique of Java NIO frameworks

Critique of Java NIO frameworks

Starting from version 1.4 Java has a new library called NIO. Everyone who writes scalable network software uses this library because it supports non-blocking network operations. Without this library, you will have a separate Thread for each connection, and Java doesn’t scale well with threads. Of course, this library is not just about non-blocking network operations. It also accelerates access to files, and has whole architecture for byte-to-char conversion and back.

Non-blocking IO is slightly harder to understand than blocking IO, but not too much. However, there are people who think that NIO is too low-level. They also think that since NIO was created to have a threading model different than “one thread per socket”, so it is a good idea to provide a threading model out-of-box. These people have written NIO frameworks. Let’s name some of them:

All those project pretend that they are “easy to use” because they “hide the complexity of plain NIO”. Is it really so ? I don’t think.

All mentioned libraries try as much as possible to hide selector, channels and bytebyffers from you. Instead, they propose “chain of responsibility” pattern, consisting of diffrent “protocol stages”. Processing on each stage could be synchronious or asynchronious.

Main problem with these frameworks is that they are too generic. They wrap 5 NIO classes with 50 their own classes. Yes, authors have analyzed >20 use cases and have created libraries which supports them all. Now, instead of manually using plain NIO in a specific way you need, you’ll have to analyze how your particular case fits into this framework, then to find out a dozen of places where you need to put pieces of your code so they will be executed in a correct sequence. They provide all the “glue” for you, so just put your “diamonds”, and overall thing will pretend to be an “iron”.

My opinion is that these frameworks should be avoided. Using them makes the code bloated and hard to understand. Better to learn NIO once. Yes, I myself often forget to flip byte buffer after reading from channel, but I prefer plain code to raviolli code. All those libraries are perfect examples of Java developers loving to produce frameworks. And this is just a part of more generic case of OO developers to love design patterns and templates.

And, final advice: if possible, don’t use NIO, use plain IO instead. If you have a single socket, then there are no reason to use Selector. If your thread should wait for the answer, make it blocking on read operation, instead of making it wait on a queue.

Update: subsequent post shows that I’ve changed my preferences from plain IO to blocking NIO. But my dislike to NIO frameworks is still here.

Update #2: Уважаемые Бауманцы! Я польщён, что вам пришлась по нраву моя статья. Буду стараться и дальше, заходите ещё. Пригласили бы, что ли, в гости, давненько не был.

Advertisements
Categories: Java
  1. Mike Heath
    April 23, 2008 at 3:30 am

    What network applications have you written that make you an authoritarian on whether or not these frameworks should be used?

    This article sounds like something written by someone who has never built and maintained a real NIO application before. NIO is tricky. Read/write buffer management can be tricky to achieve good performance. Dealing with packet fragmentation is difficult. Write buffer overflows have to be dealt with. This post is suggesting that we reinvent the wheel for every new network application that needs to built. This is asinine.

    These frameworks make the code manageable. Hard to understand? Are you serious? These frameworks provide separation of concerns which makes the code MUCH more readable and easier to test. Just because you don’t understand the benefits of these frameworks doesn’t make them bad.

    In one breath you say these framework are “too generic” and in the next you claim that you have to change your problem to fit with these frameworks. WTF? If you’re going to use event-driven networking you have to think about the problem very differently than with blocking I/O. This isn’t a framework problem. This is a fundamental lack of understanding of what NIO provides and how it can be leveraged to build highly scalable applications. Really. Do you even understand the problem NIO solves and how it should be used?

    And as for the final advice, use NIO if you need to scale to thousands of concurrent connections or have a situation where asynchronism is important but don’t use NIO directly. Take advantage of the knowledge others of learned using NIO directly and use one of these frameworks. If you don’t need such a high level of scalability, using blocking I/O is fine.

    As a side note, we’re using MINA for an internal application. MINA is faster than the plain NIO version of the app we started with. MINA provides some nice buffer management out of the box that has been very beneficial. Our tests show that using MINA’s APR transport is about 10% faster than NIO and scales *much* better than the blocking I/O version of the application we’re replacing. Did I mention that we can switch between NIO and APR changing a single line of code? Oh wait. This is bad because MINA is “too generic.”

    MINA has made our life much simpler and has given us far more performance and flexibility than using NIO directly could give us.

  2. Reza
    April 23, 2008 at 4:09 am

    I do not agree with you.
    I work with java NIO and apache MINA.
    I can make a complex socket server application with custom protocol with MINA in a day but with NIO, maybe a week.
    MINA is very easy to understand and work. believe me.

  3. kmatveev
    April 23, 2008 at 7:26 am

    For Resa:

    Sorry, but I don’t understand what do you mean by “complex socket server application” ? Main point of my post is that socket operations in both client and server applications are not complex at all. Complexity may be present in protocol-related parts of application, like parser, transactions/sessions. I really doubt that transport-related part of application is a big deal. Maybe you mean that implementing layered protocol as “chain of responsibility” is complex ? It may be, but hand-crafting it for me is easier than using a framework.

  4. kmatveev
    April 23, 2008 at 10:08 am

    For Mike:

    Hello man! You start your comment by questioning my if my experience is big enough to have right to judge about this code. Well, I suppose it is big enough, because I don’t think that “NIO is tricky”, as you say. You accuse me of being “authoritan”, but I never use words like “must”/”mustn’t”, I always say that it is just my opinion. And hey, this is my blog, I can express my opinion here! I understand that my article had probably hurt your feelings, that’s why you are attacking me personally, not my arguments. Please, don’t be rude next time! Oh dear, this blog was so quiet, but I’m afraid it will be a place of flamewar.

    OK, let’s go to the matter.

    You say “read/write buffer management can be tricky to achieve good performance”. I can’t figure out what do you mean here. That bulk ByteBuffer.get() is faster than invoking ByteBuffer.get() for each byte? Or that it is easy to forget to call ByteBuffer.flip() ? That’s not tricky, in my opinion. You say “dealing with packet fragmentation is difficult”. That is also strange for me, because UDP re-assembles a datagram for you, and reading single data from TCP stream in several parts is not tricky at all. Buffer overflow ? But I see that read() and write() methods of channels check borders of ByteBuffers!

    Then I say that I don’t like that task should be modified to fit into a framework, I meant that event-driven implementation is easier for me to do manually, through Executor interface.

    Just to convince you that my opinion deserves to be available, I will tell you why I’ve written this. I’m dealing with high-performance networking for 3 years already. Sometimes my collegues ask me: “what do you think about this library” ? So, I’ve spent my time and evaluated them. Just bloat. Too many classes. Too deep hierarchies. They don’t worth it.

    By the way, maybe you know why Tomcat and James don’t use this library ?

  5. April 23, 2008 at 10:38 am

    Nice to see a post like this. Of course there’s no solution that fits all possibilities and requirement but having developed socket servers for the last 5 years of so I’ve been playing with many of these libraries and found out that a custom NIO engine can outperform any of these framework by different orders of magnitude.

    I am not starting a fight between custom-brewed NIO vs frameworks or similar… each task requires the proper tool. I’ve been using MINA and xSocket when I was in a hurry and didn’t mind about the ultimate performance. They worked okay with a few problems here and there, but acceptable.

    For very high performance a custom solution worked much much better than Mina, so I agree with the “too generic framework” critique.

    If you’re curious about it I’ve published (last summer) a few comparison tests between a Mina-based socket server and our custom-NIO engine -> http://www.smartfoxserver.com/forums/viewtopic.php?t=1850&highlight=mina

  6. April 23, 2008 at 9:25 pm

    Interesting topic, but you don’t go into your evaluations in enough depth for your opinion to be worth much to me. I would like to see more information about what you did to actually evaluate the frameworks beyond counting classes.

    Ultimately this article boils down to the following summary: “Here are four NIO frameworks. Don’t use them. They are tricky.” How? Why? Concrete examples and comparisons please.

  7. kmatveev
    April 24, 2008 at 7:22 am

    I’m surprized to see that NIO frameworks make code fast. There are no magic inside them. They don’t encapsulate any clever algorithm, it’s just a set of abstract classes connected in patterns. Yes, there are concrete classes there, but they are mostly wrappers. So, by taking a code which uses NIO framework and inlining about 70% of methods it is possible to get plain NIO code, which will work slightly faster (because of method inlining) and will be much simpler (in my opinion).

    For me, main selling point of those frameworks is flexibility, because there are interfaces for everything.However, I don’t need this flexibility.

    I never wanted to say that those frameworks are slow. Their authors will claim that “you are just using them in wrong way”. But that is exactly my point: instead of doing something in straight way, you need spend time learning those frameworks.

    It is always possible to prove that those frameworks are not flexible enough for your case. But then authors will introduce additional layer of interfaces to satisfy you.

    Yes, my evaluation is not deep, but this is exactly the point: they are useless in advance, and even require learning. I don’t want to learn pipeline models of those frameworks, because I strongly suspect that it is a several layers of abstractions made over something very simple. I don’t want to follow stupid patterns, becase someone considers them good, and because of abstract virtues of “separation of concerns”. I belive that all those frameworks are very similar, and no one has clear benefits compared to others. It is not worth my time to see how they are different between each other, because I’m certain that finally I’ll discover that they are clones of each others, just classes have different names.

    Yes, this article doesn’t look like serious investigation, but it didn’t mean to. There are no need to look deep in code to understand that it is worthless. I know that just because socket servers simple enough to be written in plain form.

    But, if anyone wants other arguments, I have one more. Look at MINA, especially package org.apache.mina.transport.socket. There is a large amont of methods consisting of 1-3 lines of code. Just wrappers, sometimes with exception catching. This is called “code smell”, and naturally solved by refactoring “inline”.

    Can anybody name a really usefull and widespread server product which uses those libraries ? Can anybody explain why C programmers live happily without such frameworks ? Can anybody explain if those libraries are so good, why there are so many of them ?

  8. kmatveev
    April 24, 2008 at 7:38 am

    Just several quotes from Alan Perlis, which apply wery well to those frameworks.

    14. In the long run every program becomes rococo – then rubble.

    30. In programming, everything we do is a special case of something more general — and often we know it too quickly.

    52. Systems have sub-systems and sub-systems have sub- systems and so on ad infinitum – which is why we’re always starting over.

    And that is my point of view:

    31. Simplicity does not precede complexity, but follows it.

  9. April 24, 2008 at 11:46 pm

    kmatveev – you ask for an example of a widespread server using a framework on your list? Red5 is such a server, its an open source Flash media server. I am a core dev on the team and I love working with Mina, I’m not saying custom NIO wouldn’t be faster but I don’t have time to maintain such a library. If you want to waste time “rolling” your own for everything instead of using pre-built libraries that is your choice.

    http://osflash.org/red5

  10. gustav
    July 28, 2008 at 1:01 pm

    hm.

    how about you check with current technology instead of living in old dead mantras.

    NIO is currently not faster then blocking IO.
    just test it with a linux 2.6 kernel with its NPTL.

    you will see that for loads at thousands of connections, blocking IO wins with roughly 25% in all kinds of tests.

    if you run windows etc, well its your own fault if thinking its a good server.

  11. iamdeadly
    January 13, 2009 at 10:17 pm

    i agree with kmatveev that there are already too many frameworks out there. Often it takes more time to learn how to use a framework than using some basic API. NIO is not complex. The protocol symantics is what makes working with NIO difficult, not NIO itself. Rolling up your own buffer and state managers might be easier than learning another framework. i don’t have anything against a framework but in the workplace, each developer brings his own set of frameworks, and avoiding the less popular frameworks is sometimes preferable. How many of us while doing software maintenance cursed the last developer just because he used some obscure framework.

  12. Ivan Penev
    February 19, 2009 at 5:11 pm

    I have always been on the same opinion with kmatveev. So finally I decided 3 years ago to make my own simple, scalable framework. It could sound as a advertisement, but if you look here javawork.org you will find in the examples that it is really easy.

    Apache MINA has always been the preferred choice by many programmers, but I found almost no documentation, lack of simplicity and questionable high performance – what I mean is that we needed to send 2000 messages per second in our app, well, very few people usually need that much of a traffic, but shooting with MINA 1000 messages at one time brings not more than 900 at the other end.

  13. March 10, 2009 at 7:07 pm

    I harbour a deep dislike for java frameworks. They tend to be bloated things that force you to make your app into a plugin for the framework.
    I wrote a NIO *library* (rather than framework) where I tried to make working with NIO as easy, or even easier than with normal IO.
    I’m interested in knowing if you feel it suffers from the same drawbacks as the frameworks you mention. The project is called Naga and can be found at naga.googlecode.com.

  14. sfgower
    December 12, 2009 at 6:52 am

    My nio experience is quite limited, but here is my experience: I found nio very difficult to use, nor could I find non-toy working examples of non-blocking async IO on the web. So I still think there is something missing in nio. At least, it seems to me that nio is not something one can quickly pick up and use.

  1. No trackbacks yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: