Performance Comparison between NIO Frameworks

Most NIO frameworks can saturate 1 gigabit ethernet at some point. However, some frameworks can saturate the bandwidth with the smaller number of connections while others can not. The performance numbers of the 5 well-known open source NIO frameworks are presented here to help you figure out the excellence of Netty in performance.

Where’s the Graph?

If you are in a hurry, please scroll down to see the graphs first. You can also download the PDF document which contains detailed numbers and graphs.

What’s the Bottom Line?

Unlike usual expectations, NIO frameworks have different performance characteristics in spite of the fact that they are using the same NIO selector provider.

What’s observed is that the difference comes from the fundamental factors such as data structure and thread contention management, and those factors should never be overlooked.

Netty has succeeded to introduce the breakthrough in NIO framework performance with careful engineering, while retaining the flexible architecture.

Test Scenario

A simple echo server and client exchange fixed length messages one by one (i.e. synchronous ping-pong). The handler code, which sends the received data back in verbatim, is executed in a separate thread pool that each NIO framework provides.

The tests were run with different message lengths (64 ~ 16384 bytes) and different network configurations (loopback and 1 gigabit ethernet), to see how well each framework performs on various conditions.

Test Environment

  • Software
    • The test client has been written in Netty 3.0.0.CR5.
    • Echo server implementations
      • Netty 3.0.0.CR5
      • Other 4 open source NIO frameworks
        • Grizzly, MINA, NIO Framework, and xSocket
        • Used the latest milestone releases as of October 3rd, 2008
        • Excluded inactive projects (no release in 2008)
        • Framework names were anonymized in no particular order.
      • Thread pool
        • The number of I/O threads – the number of the CPU cores
        • The number of handler threads – 16
        • The default thread pool that each framework provides was used.
        • If the framework doesn’t provide a thread pool implementation which limits the maximum number of threads, Executors.newFixedThreadPool() was used instead.
      • Use of direct buffers was suppressed to avoid excessive memory consumption.
    • JRE – Sun JDK 1.6.0_07
    • JRE options – -server -Xms2048m -Xmx2048m -XX:+UseParallelGC -XX:+AggressiveOpts -XX:+UseFastAccessorMethods
  • Hardware
    • Server (Hostname: Eden)
      • CPU: 2 x quad-core Xeon 2.83GHz, ‘performance’ governor
      • O/S: Linux (Fedora 9)
      • RAM: 6 GiB
      • NIC: Broadcom NetXtreme Gigabit Ethernet PCI express
    • Client (Hostname: Serpent)
      • CPU: 2 x dual-core Xeon 3.00GHz, ‘performance’ governor
      • O/S: Linux (Fedora 9)
      • RAM: 3 GiB
      • NIC: Broadcom NetXtreme Gigabit Ethernet PCI express
    • No switching hub was used to minimized possible network latency.
  • Common TCP/IP parameters
    • TCP_NODELAY was turned on. (i.e. Nagle’s algorithm was disabled.)
    • net.ipv4.tcp_tw_recycle has been set to 1
    • Used the default MTU (i.e. 1500 – no jumbo frame)

Test Result

Client and Server on the Same Machine (Loopback Device)

The test client and servers ran on the same machine, Eden. (If images are not showing up, please refresh. There are three graphs here.)

Size=128, Loopback

Size=1024, Loopback

Size=4096, Loopback

Client and Server on Different Machines (1 Gigabit Ethernet)

The test client ran in Serpent, and the servers ran in Eden. (If images are not showing up, please refresh. There are three graphs here.)

Size=128, 1Gb Ethernet

Size=1024, 1Gb Ethernet

Size=4096, 1Gb Ethernet

Running the Tests by Yourself

The test result should be always reproduceable. Please give us your feed back to improve the accuracy of the test result. The full source code is available at the Subversion repository:

svn co

All tests run by Ant. Enter ‘ant -p‘ to see the instruction.

유명인으로 산다는 것

누구나 생애 한 번쯤 생각해 보았을 것이다. 자기 자신이 (적어도 어렸을 적에) 대통령이나 연예인이 된다거나, (아주 조금 더 현실적으로) 이름난 엔지니어가 된다거나.

하지만 조금이라도 남의 이목을 받아 본 사람이라면 유명인으로 산다는 것이 얼마나 힘든 일일 지 상상할 수 있다. 언제부턴가 내가 모르는 사람이 나를 이야기하고 알아본다는 신선한 충격은 잠시나마 즐거울 수 있겠지만, 근본적인 거리에 기인한 오해의 깊이는 어찌할 노릇이 없을테니까.

유명세는 그래서 그것을 감당할 수 있는 사람에게 주어져야 한다. 하지만 운명은 항상 우리를 예기치 않은 곳으로 데려가기 마련이어서, 나는 내가 설 그 곳에 지나친 스포트라이트가 나를 비추지 않기를 바랄 뿐이다.

… 물론 내 속의 속물 근성은 좀 다른 것을 원할 것 같지만!

Inserting Google Analytics Tracking Code using Shell Script

In most cases, you should be able to configure your CMS or blog template to insert the Google Analytics JavaScript tracking code at the end of every page in your web site.

However, you sometimes need to install the tracker code into static HTML pages which are not managed by the CMS, If you have a LOT of static HTML pages, then your fingers are in trouble.

Here’s the Bash shell script which inserts the Google Analytics tracker code into all static HTML pages. Please modify it before you run it, to meet your needs. Never forget to backup the original copy — it might work incorrectly for you:

# inject-google-analytics


TRACKER_CODE="<script type="text/javascript">
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
document.write(unescape("%3Cscript src='" + gaJsHost + "' type='text/javascript'%3E%3C/script%3E"));
<script type="text/javascript">
try {
var pageTracker = _gat._getTracker('$TRACKER_ID');
} catch(err) {}</script>"

find . -name '*' -delete
find . '(' -name '*.html' -and -not -name '*-frame.html' ')' | while read -r TARGET; do
  if grep -qiP "(<frameset|$TRACKER_ID)" "$TARGET"; then

  if grep -qiF '</body>' "$TARGET"; then
    perl -pi -e "s/(<\/body>)/\n${TRACKER_CODE////\/}\n$1/i" < "$TARGET" > "$"
    { cat "$TARGET"; echo; echo "$TRACKER_CODE"; echo; } > "$"
  if ! grep -qF "$TRACKER_ID" "$"; then
    echo "Failed to inject analytics script: $TARGET"
    cat "$"
    rm -f "$"
    exit 1
  mv -f "$" "$TARGET"

Netty 3.0.0.CR4 released with a Getting Started Guide

I wanted to write a decent guide book for the Netty project to help users get started with it very quickly, but it was not really easy to learn DocBook XML and to learn how to override several default DocBook stylesheet settings within a short period of time. Especially, I had no idea how XSL FO works when I saw it first time.

Finally, the first chapter of the Netty User Guide is now public. Other chapters are still to be written, but it’s better than having nothing. It’s available in HTML and PDF. Check it out now and give me some feed back!

Streaming Audio from Windows to PulseAudio Server

PulseAudio is a great network audio server for Linux. It allows me to stream audio between machines. However, the biggest problem with PulseAudio is that it doesn’t have a descent client implementation for Windows. There are a couple known workarounds such as using WinESD, but they are all pretty experimental. Also, the Win32 binary build didn’t work for me, perhaps because it’s somewhat outdated and buggy.

My first try was to use LineInCode and Netcat for Windows on the client side and to use module-simple-protocol-tcp on the server side. After adding -L "module-simple-protocol-tcp port=4712 rate=44100 format=s16le channels=2" option to the PulseAudio startup option, I was able to stream audio from Windows to PulseAudio server using the following command:

linco.exe -B 16 -C 2 -R 44100 | nc.exe <host> 4712

However, PulseAudio dies whenever the connection is closed because of a known issue of module-simple-protocol-tcp. I wrote some script that restarts PulseAudio whenever it dies, but I realized there’s a better solution – OpenSSH.

I have installed a Cygwin build of OpenSSH, and replaced Netcat with it:

linco.exe -B 16 -C 2 -R 44100 | ssh.exe <[email protected]> "cat - | pacat --playback"

This solution works without module-simple-protocol-tcp, and therefore there’s no need to restart the PulseAudio server on disconnection. Better security is another bonus. Instead, it requires a running SSH server. If SSHD is not running in the PulseAudio server, you can give it a little twist:

linco.exe -B 16 -C 2 -R 44100 | ssh.exe <[email protected]> "cat - | pacat --server <host> --playback"

In case your Windows machine doesn’t have a sound card or it doesn’t allow you to capture the audio stream, you might want to use Virtual Audio Cable. It’s a commercial software, but it worths a purchase.

You might also want to set up a passwordless login so you don’t have to enter the password every time you stream the audio.

영한 혼용과 똘레랑스

영어는 우리 생활 곳곳에 침투해 있다. 어떤 사람은 그것에 더 많이 익숙하고 다른 이는 그렇지 못하다. 나는 그 중간 즈음에 위치했다고 생각하고 있다. 그래서일까, 외국 생활을 오래 했다거나 외국계 회사에서 오래 일했다는 이유로 한국어 문장 속에서 영어를 혼용하는 것이 아직은 거북하게 들린다. 대표적으로 다음과 같은 것들 말이다:

  • Boss – 상사
  • Claim – 불만 사항
  • Expense – 비용
  • Industry – 업계
  • Meeting – 회의
  • Office – 사무소
  • Payroll – 월급 명세
  • Position – 직위
  • Post – 글
  • Report – 보고

수시로 문장마다 한자를 섞어 쓰는 마당에 무엇이 문제냐고 묻는다면, 그것은 아마도 익숙함의 차이 아니겠냐고 대답하겠다. 내 모든 글에서 가능한 글자를 전부 한자로 바꿔버린다면 거북해 할 사람들이 영어로 바꿀 경우보다 훨씬 많으리라고 예상할 수 있듯 말이다.

하지만 중간 즈음에 위치한 사람인 나는 혼란스럽다. 나도 모르게 섞어 말하고, 적절한 한국어 단어가 떠오르지 않는 일이 생긴다. 그러면서도 상대방에게서 그런 경우를 보면 왠지 거북하고, 그래서 내게서 그런 말이 나오면 부끄러울 때도 있다.

그런데 이것을 조금만 더 확장해 보면, 수학자가 각종 수학 용어를 섞어 일반인과 소통한다면 그것이 비록 영어가 털끝만치도 섞이지 않은 순수한 한국어라 할 지라도 거북하기는 마찬가지일 것이라고 쉽게 예상할 수 있다. 특히나 수학 기호나 미적분학 용어만 보면 멀미가 나는 사람이 대부분이라고 가정했을 때는 더욱 그렇다.

그러니까 거북함이라는 것은 어쩌면 그냥 ‘나한테 익숙하지 않아서‘인지도 모르겠다. 내가 모르거나 익숙하지 않은 말을 들었을 때 상대방이 왠지 잘난 체 하는 것 같다는 인상을 받는 것처럼 말이다.

이렇게 별의 별 것이 상대적으로 인식된다고 생각하기 시작하면 내가 남을 무제한적으로 배려해야 하는지, 아니면 그 반대인지 혼란스러워지기 시작한다. 이상적으로야 똘레랑스를 바탕으로 서로를 자유롭게 받아들여야 마땅하겠지만, 끼리 끼리 논다는 말이 좀 더 현실적이다. 결국에는 비슷한 취향의 사람들이나 서로 받아들일 수 있는 취향을 가진 사람들끼리 모이게 되는 것 같다.

그리고 이런 끼리 끼리 성향은 나이가 들 수록 고착화되고 새 친구를 사귀기 어렵게 만들어, 노년에는 세상을 떠나가는 친구들을 그리워하는 마음만 깊어지게 되는 것 아닐까, 어렴풋이 두려움을 깔고 생각해 본다.

추석맞이 이직 1년 결산

9월 1일, 이직을 했다. 나는 덕택에 풀타임 오픈 소서 및 수석 소프트웨어 엔지니어라는 명칭을 얻었다. 전보다 훨씬 많은 급여를 받게 되었다. 거기다가 마치 ‘노동의 미래‘나 ‘세계는 평평하다‘를 그대로 옮겨 놓은 듯한 재택 근무 작업 환경도 차렸다.

무엇을 사더라도 예전보다도 ‘더 멋진’ 물건을 찾기 시작했다. 더 많은 음반이 아마존을 통해 내 콜렉션에 추가되었다. 더 좋은 의료 서비스를 받을 수 있게 되었고, 그 결과 전반적인 건강상의 향상도 얻었다. 이 정도라면 거의 모든 면에서 내 삶의 질은 진보했다, 라고 평할 수 있을까?

다소 설명하기 어렵지만, 그에 비해 내면의 질은 많은 향상을 필요로 하고 있다. 나는 전보다 더 바빠졌다. 수영왕 펠프스가 연습시간에는 수영을 하고, 수영 녹화 영상을 보는 것으로 여가를 보낸다면, 프로그래밍왕도 아닌 나는 시간대를 허물어가며 업무 시간에는 프로그래밍을 하고, 프로그래밍으로 여가를 보내고 있다.

아마도 그것은 단순히 새 직장 때문은 아닐 것이다. 그저 나의 프로그래밍에 대한 순수한, 아니 본능에 가까운 욕구가 새 직장이라는 침실을 차지하게 되면서 생긴 예측된 수순에 다름없다. 이러한 실락원에서나 볼법한 뜨거운 만남은 나를 자발적 과로로 인한 커리어 파멸로 이끌 것인가, 아니면 다음 단계로의 도약으로 이끌 것인가.

정답이 없는 것이 당연하다고 할 수 있겠지만, 그래도 어떻게 될 지 내 스스로도 모르겠다. 나는 전보다 교양서나 소설을 더 적게 읽는다. 뿐만 아니라 기술서도 더 적게 읽는다. 이 상황의 심각성은 내가 ‘알만큼 알아서‘와는 거리가 먼 상황에 놓여 있기 때문에 더욱 두드러진다. 한 때 날렸던 누군가가 새로 들어온 똑똑한 친구에게 험담이나 당하는 꼴을 상상하게 되는 것은 한 때 그 ‘똑똑한 친구‘에 해당했던 나로서는 당연한 일이 아닐 수 없다.

나는 어디까지 갈 수 있고, 또 어디까지 가야 하는가. 그것은 다르게 말한다면 ‘내가 가장 유능할 수 있는 위치는 어디까지이고, 내가 가장 무능할 수 있는 위치는 어디부터인가‘일 것이다. 그리고 그 위치는 지금으로서는 뭐랄까, 다소 무섭게 다가온다.

그렇기에 오늘도, 조금은 힘들지만 변화를 꿈꾼다.

한국 미나 사용자께 드리는 네티로의 전환 권고

미나 프로젝트에서 손을 뗀 후, 지난 약 3개월간 네티 프로젝트 에 상당한 시간을 할애하였고, 그 결과 현재 API 와 구현 모두 안정화 단계에 접어들었습니다.

적절한 문서화, 공개 가능한 성능 테스트 보고서 작성 및 웹 사이트 컨텐츠 보강을 마치는 대로 최초의 안정 버전이 릴리즈될 예정입니다. 지금까지 적어도 2 주에 한 번씩은 릴리즈를 해 왔고, 앞으로 2 주 내로 릴리즈 계획이 되어 있으므로, 미나처럼 불필요하게 프로젝트의 릴리즈가 늦어지는 일은 없을 것으로 예상합니다.

네티 안정 버전의 릴리즈와 동시에 미나 프로젝트에 대한 한국어 지원에 할애하는 시간을 많이 줄일 예정이니, 양해 부탁드리겠습니다. (상황에 따라 답장을 못 보내 드릴 수도 있습니다.) 따라서 모든 미나 관련 문의는 공식 커뮤니티를 통해 해 주시면 감사하겠습니다.

네티 프로젝트는 제가 직접 운영하는 한국어 사용자 그룹을 갖고 있습니다. 따라서 네티 프로젝트에 대한 모든 문의 사항 및 피드 백은 네티 한국어 사용자 그룹 을 통해 해 주시면 성심 성의껏 회신하도록 하겠습니다.

만약 진행중이신 프로젝트가 초기 단계에 있다면 네티로의 전환을 심각하게 고려하시기를 권합니다. 부가 기능 (예: JMX) 면에서 부족함이 있으나, 스루풋, 레이턴시, 유연성, 안정성 등 대부분의 면에서 비교할 수 없는 경험이 되리라 확신합니다.