Montag Aug 31, 2009

High-performance TCP/IP programming on the JVM

I've recently created a white-paper about several options to do TCP/IP programming on the JVM. I'm giving here the introduction and the table of contents to give you an impression what's this all about. The white-paper comes with full source-code and is 27 pages long, so it's a bit too much for a blog entry. Get it here, if you want to take a look.

Introduction

The purpose of this document is threefold. Firstly, it should give the reader a historical overview of the TCP/IP networking API's, programming paradigms, and various coding styles on the Java Virtual Machine. Secondly, it presents a couple of new options, programming-models, and demonstrates the same with Scala, one of the new languages available on the JVM. Lastly, a small and simple benchmark was conducted, to relate these different strategies with to each other on the metrics of performance.

The discussion is centred wholly around the Java Virtual Machine for a couple of reasons. First and foremost, one regularly deals with several programming languages and several libraries. Basing everything around the JVM provides the opportunity to eliminate issues such as the language implementation, memory management, interfaces to the host operating-system, etc. Besides this advantage, the JVM is the foundation for a large amount of Open Source libraries, tools, including excellent support from a couple of free IDEs that it became the platform of many web applications. The platform is mature, versatile and widely available.

To showcase the various API's, languages and programming models, and to give the programmer an impression as to how such source code looks like, five very trivial server programs that write a simple HTML page to any client, which tries to open a TCP/IP connection to such a server, were created. Since all five programs run on the Java Virtual Machine, this page-generating method has converged to a single utility-class, which is shared among the five programs. Therefore, risks arising from inconsistent behaviour and performance, because the programs were developed in different programming languages - Java and Scala, were eliminated.

Table of Contents

Introduction

Classic Java networking IO:Sockets

One connection = one Thread?

Java New I/O: Java NIO

Buffers/Channels

Non-blocking I/O

NioServer example

NIO Frameworks, enter: Grizzly

Problems with plain NIO

The Grizzly NIO framework

The Actor Model

Network API evolution

Threading API evolution

Actors: shared-nothing versus shared data

Scala

Functional and Object-Oriented programming combined

Statically typed

Running inside the Java Virtual Machine

Modern language constructs: closures, type interference, pattern matching, powerful literals etc.

Excellent Actor library nicely integrated in the language

A simple Scala server using the Actor Model

Sending messages

Receiving messages

Combining the Actor Model and NIO

The Benchmark

Benchmark setup

Observations

Page generation

Conclusion

Dienstag Mai 12, 2009

UNIX DaytimeServer - the Scala way

I'm playing around with Scala. No, frankly I'm in love with it. While reading through "Programming in Scala" (which is a perfect introduction into the subject), I converted the Daytime Server into a Scala version. Get the NetBeans Project.

Here's how it looks like:

 

 1 package daytimeserver
 2 
 3 import java.io.IOException
 4 import java.nio.ByteBuffer
 5 import java.util.Date
 6 import java.nio.channels.SelectionKey
 7 
 8 import com.sun.grizzly.{ ProtocolFilter, Context, Controller, ProtocolChain,
 9                          DefaultProtocolChain, ProtocolChainInstanceHandler, TCPSelectorHandler }
10 
11 import com.sun.grizzly.util.OutputWriter
12 
13 class MyTCPSelectorHandler extends TCPSelectorHandler {
14 
15     override def onAcceptInterest(key:SelectionKey, ctx: Context ) : Boolean = {
16         var channel = acceptWithoutRegistration(key)
17 
18         if (channel != null) {
19             configureChannel(channel)
20             var readKey = channel.register(selector, SelectionKey.OP_READ | SelectionKey.OP_WRITE)
21             readKey.attach(System.currentTimeMillis())
22         }
23         
24         false
25     }
26 }
27 
28 class MyProtocolChainInstanceHandler extends ProtocolChainInstanceHandler {
29 
30     private var protocolChain = new DefaultProtocolChain()
31 
32     def poll() : ProtocolChain = protocolChain
33     def offer(instance: ProtocolChain ) : Boolean = true
34 }
35 
36 class DaytimeWriterFilter extends ProtocolFilter {
37 
38     def execute(ctx: Context) : Boolean = {
39         if (ctx.getProtocol() == Controller.Protocol.TCP) {
40             var channel = ctx.getSelectionKey().channel()
41             var now = (new Date()).toString() + "\\n"
42             var buffer =  ByteBuffer.wrap(now.getBytes())
43 
44             OutputWriter.flushChannel(channel, buffer)
45 
46             channel.close()
47             buffer.clear()
48         }
49         false
50     }
51 
52     def postExecute(ctx : Context ) : Boolean  = false
53 }
54 
55 object DaytimeServer extends Application {
56 
57     val PORT : Int = 1405
58     var controller = new Controller()
59     var tcpSelectorHandler = new MyTCPSelectorHandler()
60     var pciHandler = new MyProtocolChainInstanceHandler()
61     var protocolChain = pciHandler.poll()
62 
63     tcpSelectorHandler.setPort(PORT)
64     controller.addSelectorHandler(tcpSelectorHandler)
65     controller.setProtocolChainInstanceHandler(pciHandler)
66     protocolChain.addFilter(new DaytimeWriterFilter())
67 
68     try {
69         println("Starting Daytime server running on port " + PORT)
70         controller.start()
71     } catch {
72         case ex: IOException => println("Exception:" + ex)
73     }
74 }
75 
About

schmidtm

Search

Archives
« April 2014
MoDiMiDoFrSaSo
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
    
       
Heute