Home > Uncategorized > Tricks and Tips with NIO part VI: Heap, View or Direct ByteBuffer, which one perform the best?

Tricks and Tips with NIO part VI: Heap, View or Direct ByteBuffer, which one perform the best?

Choosing the right byte buffer is not simple. Correct me if I’m wrong, but there is little documentation about which type of byte buffer to choose when writing scalable server. So here is some informal observations I’ve made when using the Grizzly WebServer

There is three types of byte buffer:

neig2.jpg

  • Direct Byte Buffer [ByteBuffer.allocateDirect()]: Given a direct byte buffer, the Java virtual machine will make a best effort to perform native I/O operations directly upon it.
  • Heap Byte Buffer [ByteBuffer.allocate()]: A byte buffer backed by a byte array.
  • View Byte Buffer [ByteBuffer.slice()]: a byte buffer whose content is a shared subsequence of direct or heap byte buffer’s content.

Since no data/benchmarks where available on the topic at the time we’ve written Grizzly, the type is easily configurable via system properties. For the view byte buffer, Grizzly creates a very large one and slice it like this:

     68     public synchronized static ByteBuffer allocateView(int size, boolean direct){
     69         if (byteBuffer == null ||
     70                (byteBuffer.capacity() - byteBuffer.limit() < size)){
     71             if ( direct )
     72                 byteBuffer = ByteBuffer.allocateDirect(capacity);
     73             else
     74                 byteBuffer = ByteBuffer.allocate(capacity);
     75         }
     76
     77         byteBuffer.limit(byteBuffer.position() + size);
     78         ByteBuffer view = byteBuffer.slice();
     79         byteBuffer.position(byteBuffer.limit());
     80
     81         return view;
     82     }

I didn’t run any micro benchmark, but here is some simple results using Grizzly WebServer.I didn’t set any special VM config, just the Grizzly out of the box configuration. For stressing the server, I’ve used ab, which is not the best/viable tool for benchmarking but the easiest to use. The JDK version used is:

java version "1.6.0"
Java(TM) SE Runtime Environment (build 1.6.0-b105)
Java HotSpot(TM) Client VM (build 1.6.0-b105, mixed mode, sharing)

I’ve run 100 times the following command and calculated the means:

% ab -q -k -n1000 -c600

and got the following result.

Direct ByteBuffer: 2241 tx/s with the following config:

% java -Dcom.sun.enterprise.web.connector.grizzly.useDirectByteBuffer=true 
-jar grizzly-framework.jar 8080 /s1/domains/domain1/docroot/
Jan 23, 2007 12:10:58 PM 
INFO:
 Grizzly configuration for port 8080
         maxThreads: 5
         minThreads: 5
         ByteBuffer size: 8192
         useDirectByteBuffer: true
         useByteBufferView: false
         maxHttpHeaderSize: 8192
         maxKeepAliveRequests: 256
         keepAliveTimeoutInSeconds: 30

Heap ByteBuffer: 2269 tx/s with the following config:

% java -Dcom.sun.enterprise.web.connector.grizzly.useDirectByteBuffer=false 
-jar grizzly-framework.jar 8080 /s1/domains/domain1/docroot/
Jan 23, 2007 12:19:34 PM 
INFO:
 Grizzly configuration for port 8080
         maxThreads: 5
         minThreads: 5
         ByteBuffer size: 8192
         useDirectByteBuffer: false
         useByteBufferView: false
         maxHttpHeaderSize: 8192
         maxKeepAliveRequests: 256
         keepAliveTimeoutInSeconds: 30

View Direct ByteBuffer: 2304 tx/s with the following config:

% java -Dcom.sun.enterprise.web.connector.grizzly.useByteBufferView=true 
-Dcom.sun.enterprise.web.connector.grizzly.useDirectByteBuffer=true 
-jar grizzly-framework.jar 8080 /s1/domains/domain1/docroot/
Jan 23, 2007 12:31:01 PM 
INFO:
 Grizzly configuration for port 8080
         maxThreads: 5
         minThreads: 5
         ByteBuffer size: 8192
         useDirectByteBuffer: true
         useByteBufferView: true
         maxHttpHeaderSize: 8192
         maxKeepAliveRequests: 256
         keepAliveTimeoutInSeconds: 30

View Heap ByteBuffer: 2484 tx/s with the following config:

% java -Dcom.sun.enterprise.web.connector.grizzly.useByteBufferView=true 
-Dcom.sun.enterprise.web.connector.grizzly.useDirectByteBuffer=false 
-jar grizzly-framework.jar 8080 /s1/domains/domain1/docroot/
Jan 23, 2007 12:38:43 PM 
INFO:
 Grizzly configuration for port 8080
         maxThreads: 5
         minThreads: 5
         ByteBuffer size: 8192
         useDirectByteBuffer: false
         useByteBufferView: true
         maxHttpHeaderSize: 8192
         maxKeepAliveRequests: 256
         keepAliveTimeoutInSeconds: 30

Surprisingly, the views from an heap byte buffer are always performing better. But before drawing conclusion, I also did similar test using Apache JMeter and got the same kind of results. Hence I’m tempted to conclude that Heap Byte Buffer will always perform better, and views from heap byte buffer is the type to use when possible. As usual, it might be Grizzly specific numbers, so I recommend you test the various type before making a choice….but I can bet view byte buffer will always perform the best! Of course, if someone has time to write a micro benchmark, make sure you drop your results here.

_uacct = “UA-3111670-1″;
urchinTracker();

technorati:

About these ads
Categories: Uncategorized
  1. No comments yet.
  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

Follow

Get every new post delivered to your Inbox.

Join 51 other followers

%d bloggers like this: