How to Work Around IntelliJ IDEA 8 UI Slowdown Issue with Intel X11 Driver

I have been trying to switch from Eclipse to IntelliJ IDEA recently. However, IDEA 8, the latest version, has shown me horribly unresponsive UI. Especially, the slow scroll in the editor window was intolerable; any keystroke that involves scrolling took up 100% CPU and only a couple lines were scrolled for a second. I could hardly edit my source code and had to go back to Eclipse.

Today, I’ve finally figured out what exactly was causing the problem – the intel video driver of X.org X11 server. In Fedora 10, the default video acceleration method of the intel video driver is ‘EXA’. According to the man page of the intel video driver (type man intel in your terminal), EXA is a newer and simpler acceleration architecture designed to better accelerate the X Render extension.

However, it seems like there’s a known performance issue with EXA that slows down most Java Swing applications and some web pages in Firefox. So, I switched back to XAA, the old XFree86 based acceleration architecture. Switchback is as simple as modifying the Device section of the /etc/X11/xorg.conf file:

Section "Device"
    Identifier  "Default Video Card"
    Driver      "intel"
    ...
    Option      "AccelMethod"  "XAA"
    ...
EndSection

After restarting the X server, I am seeing noticeable improvement in the responsiveness of all GUI applications including IDEA 8, Firefox, and even some GTK+ applications.

Update (Dec 16, 2008)

However, some users have reported that switching back to XAA causes artifacts in rendering and segmentation faults in some applications. Actually, I also experienced some UI glitches in a particular application, but I didn’t care much about it. A couple days ago, I found a way to improve the overall performance of EXA. Update your xorg.conf as follows:

Section "Device"
    Identifier  "Default Video Card"
    Driver      "intel"
    ...
    Option      "AccelMethod"          "EXA"
    Option      "MigrationHeuristic"   "greedy"
    Option      "ExaNoComposite"       "false"
    Option      "ExaOptimizeMigration" "true"
    ...
EndSection

IntelliJ wouldn’t perform as well as XAA, but you will find it acceptable.

Removing Old Continuum Build Results Automatically

I am using Apache Continuum as a continuous integration server to test Netty, the Java NIO Client Server Network Application Framework.

I’m pretty satisfied with the CI server since it’s running more than 1000 Netty test cases about 4000 times a day with 7 different JDKs (see the live report here). It increases the chance for me to catch a hidden race conditions which might cause a problem in a production environment. I actually was able to find a couple critical issues like a dead lock thanks to the intensive automated testing.

However, the caveat of running big number of tests a day is that too many build results are filed into the build report database, slowing down the overall performance of the CI server. Moreover, Continuum doesn’t provide the paginated view of build results at this moment, and therefore the large number of build results can lead to high memory footprint and poor UI response time.

So, I ended up with a simplistic tool that removes the successful build results which are older than the certain amount of time (e.g. 6 hours). Continuum provides an easy-to-use client API which is based on XMLRPC, so it didn’t took long.

I run reap-old-builds command every 10 minutes to keep the build result set as small as possible, and now Continuum is responding much faster than before. If you are interested, please check my latest work from the following Subversion repository:

  • https://t.motd.kr/repo/svn/continuum-tools/trunk

Ant2IDE – IDE project file generation from Ant build.xml

Ant2IDE generates Eclipse (or other IDE-specific) project files with proper classpath and source folder settings from Ant build.xml automatically.
I wrote ant2eclipse long time ago with my crude shell script skill to generate Eclipse project files from an Ant build.xml file.
In Ant2IDE, I extended the idea so that it works in a more elegant way using the BuildListener interface. The usage is pretty simple:

  1. Add ant2ide.jar to the classpath:
    export CLASSPATH="/usr/local/libexec/ant2ide.jar:$CLASSPATH"
  2. Change the working directory to the project home:
    cd /home/trustin/workspace/myAntProject
  3. Clean the build
    ant clean
  4. Run ant with the -listener option and appropriate task(s):
    ant -listener net.gleamynode.ant2ide.EclipseProjectGenerator compiile-main compile-test

You might prefer to use the following simple shell script:

#!/bin/sh
# Path: /usr/local/bin/ant2eclipse
export CLASSPATH="$CLASSPATH:/usr/local/libexec/ant2ide/ant2ide.jar"
ant -listener net.gleamynode.ant2ide.EclipseProjectGenerator "[email protected]"

How it works

How does Ant2IDE generate the Eclipse project files? It listens to the build events fired by Ant and records the source and destination directory of the javac tasks into its internal data structure. Once build is completed successfully, Ant2IDE processes the recorded information to generate IDE-specific project files. It’s very simple but it works much better than analyzing build.xml directly or creating a new Java project from an Eclipse workbench.

Caveats

Of course, Ant2IDE is not a silver bullet – there’s some limitation in this approach.
First, you can’t get the correct build information unless you provide a proper Ant target. For example, clean target will never help AntIDE generate the project files. You should specify the target that compiles all source code, such as build-all or all, test-all.
Second, it doesn’t add all resource directories automatically. You have to add them manually for most cases. There’s no way to determine exactly whether a copy task copies resource files for now. One exception is when your project has a directory layout which is similar to that of Maven 2 project; Ant2IDE looks for a resources directory when the name of the source code directory is java, and add the resources directory to the source path automatically.
Third, Eclipse JDT is the only IDE that Ant2IDE supports at this moment. It’s designed to support other IDEs such as NetBeans and IntelliJ, but I don’t use them these days. Any contribution would be great.

Changelog

  • Nov 19, 2008 – Added auto-detection of resources directory
  • Nov 14, 2008 – Initial implementation

Opening a new tab in an existing GNOME terminal window

Use RoxTerm instead – 'roxterm --tab' opens a new tab in an existing terminal window, with no hack described here.

GNOME terminal has great support for tabbed terminal sessions. You can simply open a new tab by pressing CTRL+SHIFT+T and it’s very convenient.

However, it seems like there’s no straightforward way to ask gnome-terminal command to reuse an existing window and add a new tab there. I tried various options like --tab, but they didn’t work as I expected. I just want to keep only one terminal window in my desktop, but it looks like there’s no command line option that does the job.

So, I wrote a shell script that adds a new tab to an existing GNOME terminal window when there is already a running instance. It also launches a new terminal window if necessary:

#!/bin/bash
# Path: /usr/local/bin/gnome-terminal
if [ "x$*" != "x" ]; then
  /usr/bin/gnome-terminal "[email protected]"
else
  pgrep -u "$USER" gnome-terminal | grep -qv "$$"
  if [ "$?" == "0" ]; then
    WID=`xdotool search --class "gnome-terminal" | head -1`
    xdotool windowfocus $WID
    xdotool key ctrl+shift+t
    wmctrl -i -a $WID
  else
    /usr/bin/gnome-terminal
  fi
fi

This script looks for an existing gnome-terminal window, sends CTRL+SHIFT+T key event there, and raises the terminal window. Please note that xdotool and wmctrl are required to run the script. They should be available in most Linux distributions.

It’s just a band-aid solution – I hope I can get rid of this script from my system when the next release of GNOME terminal is out.

내가 하는 일은 세상을 (어떻게) 바꾸는가

스스로 최선을 다하게 되는 데는 여러 가지 이유가 있기 마련이다. 나는 주로 내가 하는 일이 이 세상을 어떻게 바꾸게 될 것인가에 대해 주로 생각한다. 그리고 어느 시점까지는 그런 생각을 통해 많은 부분에서 성공적인 시간을 보내 왔던 것 같다.

그런데 최근의 여러 가지 일들을 통해 이 주제에 대해 재고하게 될 기회가 생겼다. 여러 가지 일들이라고 해서 그렇게 특별한 것은 아니다. 주로 업무상의 의도치 않은 일시적 태만이라든지, 학습에의 가볍고 일시적인 강박이라든지, 사소한 일들이 주를 이룬다. 물론 미나 프로젝트를 떠나면서 사색의 시간을 좀 더 할당받았기 때문이라는 큰 이유도 있겠지만.

소프트웨어 개발을 포함한 대부분의 일은 세상을 바꿀 수 있다. 그것이 아무리 하찮을 지라도 세상을 바꾼다는 것은 의심의 여지가 없다. 하지만 동시에 대부분의 일들에 있어 우리의 행위가 세상을 어떻게 바꿀 지에 대해서는 논란의 여지가 크다는 것도 의심의 여지가 없다. 내가 작성한 소프트웨어로 크루즈 미사일 을 제어할 수도, 해저 자원 탐사 로봇을 제어할 수도 있다. 그뿐인가. 크루즈 미사일이 세상을 좋게 바꾸느냐 그렇지 않느냐는 더 큰 논란의 여지를 낳는다.

이런 관점에서 보았을 때, 솔직히 지적 유희나 이윤의 추구를 위한 일이 덜 가치있다고 말할 만한 논거가 잘 떠오르지도 않는다. (참, 그런데 그 가치라는 건 또 어떻게 평가하지?) 그렇게 생각이 꼬리에 꼬리를 물다 보면 세상을 바꾼다는 말이 생각보다는 별로 흥미 진진한 일만은 아닌 게 아닌가 싶어진다. 그렇다고 해서 딱히 스트레스를 받는다거나 하는 것도 아니다. 하지만 뭔가 김빠지는 것만은 틀림없다.

좀 더 현실적인 문제로 돌아갈 필요를 느낀다. 그래서 더 학습에 대해 강한 욕구를 느끼는지도 모르겠다. 하지만 미완의 사색에는 찜찜한 구석이 있다.

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 2.6.25.11-97.fc9 (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 2.6.25.11-97.fc9 (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 http://anonsvn.jboss.org/repos/netty/subproject/benchmark

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:

#!/bin/bash
# inject-google-analytics

TRACKER_ID="UA-XXXXX-X"

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

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

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

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 JBoss.org 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!