Navigation

RSS 2.0 New Entries Syndication Feed Atom 0.3 New Entries Syndication Feed

Show blog menu v

 

General

Use it

Documentation

Support

Sibling projects

RIFE powered

Valid XHTML 1.0 Transitional

Valid CSS!

Blogs : Latest entries

Myth: Java can't scale down

In the recent case of Java's versus The Scripting Languages, I'm seeing a pattern appear of people that claim that Java can't scale down and always has to take up a huge amount of memory before being able to run adequately. So, I decided to take a look myself to see how low I could press a Bla-bla List setup. This isn't meant to be a comparative benchmark, just a collection of numbers to show that Java does scale down and up (and sideways, but that's another story).

I performed this on our current main server (which is by no means inactive). The specs of the machine are as follows:

Dell PE1850 (2 x Xeon 2,8Ghz / 2GB DDR / 2x146GB SCSI RAID1)
Linux version 2.6.10-gentoo-r6 (gcc version 3.4.3-20050110 (Gentoo Linux 3.4.3.20050110, ssp-3.4.3.20050110-0, pie-8.7.7)) #4 SMP

The Java virtual machine and servlet engine are the following:

java version "1.5.0" Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0-b64)
BEA WebLogic JRockit(R) (build dra-38972-20041208-2001-linux-ia32, R25.0.0-75, GC: System optimized over throughput (initial strategy singleparpar))
Caucho Resin 3.0.12

I didn't setup anything in particular and just copied over the current Bla-bla List web application to the Resin webapp dir, and ran it on port 8090.

The page I'm using for the tests is the same as http://blablalist.com/list/gbevin/blablalist. The output of this page goes through the whole RIFE web engine stack until the actual element (similar to an action) is reached. There I set up OSCache to cache the output for 15 seconds at a time (source). Please don't judge this cache integration, it's very crude and could be done better and in a general fashion, but that's not the point here.

And now for the tests ...

Myth: Java can't scale down

I set up the virtual machine with these options:

-server -Djava.awt.headless=true -Xms16M -Xmx16M

To check the performance, I used Apache HTTPd's ab command, and this is the commandline and the output.
(I ran it once beforehand to let the virtual machine warm up).

dawn root # ab2 -n 10000 -c 10 http://blablalist.com:8090/list/gbevin/blablalist 
This is ApacheBench, Version 2.0.41-dev <$Revision: 1.121.2.12 $> apache-2.0
<snip>
Server Software:        Resin/3.0.12
Server Hostname:        blablalist.com
Server Port:            8090

Document Path:          /list/gbevin/blablalist
Document Length:        12795 bytes

Concurrency Level:      10
Time taken for tests:   23.85976 seconds
Complete requests:      10000
Failed requests:        0
Write errors:           0
Total transferred:      129156652 bytes
HTML transferred:       127975590 bytes
Requests per second:    433.16 [#/sec] (mean)
Time per request:       23.086 [ms] (mean)
Time per request:       2.309 [ms] (mean, across all concurrent requests)
Transfer rate:          5463.45 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    0   0.2      0       3
Processing:     0   22  32.3      3     107
Waiting:        0    1   1.5      2      98
Total:          0   22  32.3      3     107

Percentage of the requests served within a certain time (ms)
  50%      3
  66%      4
  75%     64
  80%     68
  90%     77
  95%     82
  98%     87
  99%     90
 100%    107 (longest request)

Thus, by only giving 16 megabytes of heap to the virtual machine, I still got a whopping 433 requests/second with a concurrency of 10.

Myth: Java is slow (even though it can scale up)

For this test I simply increased the memory heap of the virtual machine to 64MB, like this:

-server -Djava.awt.headless=true -Xms64M -Xmx64M

After doing one JVM warm-up run, the results of ab are the following.

<snip>
Concurrency Level:      10
Time taken for tests:   3.940688 seconds
Complete requests:      10000
Failed requests:        0
Write errors:           0
Total transferred:      129138192 bytes
HTML transferred:       127958074 bytes
Requests per second:    2537.63 [#/sec] (mean)
Time per request:       3.941 [ms] (mean)
Time per request:       0.394 [ms] (mean, across all concurrent requests)
Transfer rate:          32002.28 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    0   0.3      0       3
Processing:     0    3   6.5      2      82
Waiting:        0    1   1.8      1      55
Total:          0    3   6.5      2      82

Percentage of the requests served within a certain time (ms)
  50%      2
  66%      3
  75%      3
  80%      3
  90%      4
  95%      4
  98%     24
  99%     40
 100%     82 (longest request)

So by using a mere 64 megabytes of heap, the performance increased to 2537 requests/second with a concurrency of 10. Just for completeness, with 32MB I got 1553 req/sec and higher memory settings didn't have much influence anymore at this level of concurrency.

Remember, the cache is not providing pre-generated static html pages that are served directly by a web server (as some other frameworks do). Each request really goes through the whole Java web framework and its web engine before the cache can do its work.

Truth: Java excels at both

I was actually quite amazed that it only took 64MB to let the benchmark perform at its best and that the minimal requirements were as low as 16MB (JRockit wouldn't accept a lower setting). It's about time that people stop judging Java by its characteristics of the initial 1.0 release. Modern JVMs and servlet engines deliver truly outstanding performance in any environment.

posted by Geert Bevin in Java on Apr 8, 2005 3:21 PM : 9 comments [permalink]
 

 
 
 
Google
rifers.org web