Wednesday, August 25, 2010

tmpfs and PostgreSQL

I've been dreaming to have an SSD for quite a long time. In order to reduce disk operations when I actually have an SSD, I practiced to
  • point browser.cache.disk.parent_directory of Firefox to /dev/shm
  • remove swap partition
  • move several temporary folders to tmpfs.
tmpfs /var/log/apt tmpfs noatime,defaults 0 0
tmpfs /var/log tmpfs noatime,defaults 0 0
tmpfs /tmp tmpfs noatime,defaults 0 0
tmpfs /var/tmp tmpfs noatime,defaults 0 0

It works beautifully until I installed PostgreSQL for a project on my laptop, because it needs one more folder for logs. Here is the workaround.

sudo mkdir /var/log/postgresql
sudo service postgresql-8.4 start

Enjoy taking the advantage of my 4GB memory.

Wednesday, August 11, 2010

Good practice in using java.util.concurrent

Concurrent package was introduced from Java 5 and still doesn't get reasonable acceptance. Traditional thread programming is just too strong for us to unlearn it. Several years ago, I created a task framework to solve commonly used scenario, a modified version (most changes are generic related) is used in a product I participated in 2008.

In my current project, I have a requirement of setting timeout for serials of web service operations, which is very suitable for concurrent package. I learned a good lesson from this simple task. I reckon I need to revise my framework one day.

The 1st lesson I learned is it's harder and not safe to set thread name to a Callable thread. One workaround is calling Thread.currentThread().setName() at the beginning of call(). But thread is not owned by Callable but by ExecutorService, so this might have some side-effects. Use it at your own risk.

The 2nd one is the overhead of creating and removing threads is much heavier than I imaged before. In debug mode you can see the process of creation and removal of threads, especially when you submit the thread in loops. Try your best to minimize the operations in call() and only call call() when necessary.

Third tip is by using Future.get(1L, TimeUnit.MILLISECONDS) and ignoring TimeoutException you get an asynchronized thread.

Last but not least is always cancel future and shutdown service. If you fail to do so, the callable will be in running status forever and eventually you'll have no memory to create any new thread. Although I don't see any difference between Future.cancel(true) and Future.cancel(false), ExecutorService.shutdown() and ExecutorService.shutdownNow() in my case.