By user9154807 on Nov 04, 2014
A friend/customer asked a question about the startup times of Java SE Embedded running on a certain flash-based embedded system. There were two initial questions that I had:
- Did Java startup time depend much on SD card speed?
- Did Java startup time depend much on the "compact profile" used, and related options.
I didn't have access to his system, so I decided to first experiment on something I could get my hands on - a Raspberry Pi B+. I also picked up some micro SD cards for testing.
If tl;dr, scroll to Final Results.
Micro SD Card Info
- Micro Center 4GB Class 4 ($4). Whenever I've wanted the slowest possible flash memory, generic Micro Center flash cards have never disappointed me.
- Toshiba 8GB 8GB Class 10, UHS-I (30mb/s).
- SanDisk 8GB Class 4.
I benchmarked the random IO speed of these thread cards running on the Raspberry Pi (2014-09-09-wheezy-raspbian), using the iozone program (iozone -e -I -a -s 50M -r 4k -r 512k -i 0 -i 1 -i 2). Note that the "-I" option tries to bypass the linux buffer cache, which should more closely mimic doing "cold start" runs.
This produced a lot of data (see appendix at end), but here's a subset:
|Iozone random (K/s)||4K read||4K write||512K read||512k write|
|MC Class 4||2655||4||6523||540|
|Tosh Class 10||3717||25||18003||1313|
|SanDisk Class 4||4923||707||18480||2106|
The linux page size while reading a memory-mapped file (libjvm.so, for example) is 4K, so the numbers that should affect startup time the most are random 4K reads.
The Class 4 SanDisk seems to be the winner in 4K random reads.
Compact Profile Info
Compact Profiles are a feature added in JDK SE Embedded 8 which allow smaller subsets of a full JRE to be installed on an embedded system. There are several things that get tuned when selecting the compact profile and optional features including:
- What Java APIs are supported. Compact1 has the smallest subset of Java, Compact2 adds JDBC, RMI, etc., Compact 3 adds Security, Management, and Instrumentation. The "full" SE API includes AWT, SWING, CORBA, etc.
- JVM builds - "minimal" has only one GC (serial) and no servicability features, "client" corresponds to the normal JRE client JVM.
- Debug support - does the JVM support the JVMTI interface, and do the jar files contain debug info.
- Compression - are the jar files compressed or not.
- Compact 1 (cp1): 10.8 MB
- Compact 2 (cp2): 15.1 MB
- Compact 2 with debug info (cp2.debug): 20.7MB
- Compact 2 with debug info an uncompressed jar files (cp2.debug.big): 35.4MB
Two sub-questions are:
- Does the Java startup time vary with Java distribution size?
- Does the Java startup time go up or down with uncompressed jar files? Is there an SD card slow enough that the CPU time saved by not having to decompress the files is outweighed by the extra IO time?
To test startup time I ran the "startup.helloworld" sub-test from specjvm2008 10 times for each configuration and took the average "user time" (on a pretty quiet raspberry pi, no X, etc.).
So the faster SD card does speed up Java startup by 7-8%. There is little difference between cp1 and cp2, but the extra debug info in cp2.debug does become a drag. The big surprise to me is that using uncompressed jar files speeds up startup time by 4-5% even on the slowest SD card.
Another way to view it is to compare startup times of other profiles to the cp1 profile, and startup times of other SD cards to the Microcenter SD cards:
This experiment didn't cover a very broad range of Micro SD cards (there are more expensive cards available with higher advertised performance, but they tend to be optimized for large sequential read/writes). But it looks there's an easy 10%+ variance in Java startup times depending on SD card speed and JRE configuration.
There are a lot of posts about SD card speed and Raspberry Pi performance (boot times, etc). See http://elinux.org/RPi_SD_cards#SD_card_performance, http://www.raspberrypi.org/forums/viewtopic.php?f=2&t=4076, http://www.raspberrypi.org/forums/viewtopic.php?f=63&t=54169, etc.
Full iozone data:
$ iozone -e -I -a -s 50M -r 4k -r 512k -i 0 -i 1 -i 2
|Iozone:||KB||reclen||write||rewrite||read||reread||Random read||Random write|
|MC Class 4||51200||4||770||804||3140||3141||2655||4|
|Sandisk Class 4||51200||4||1292||1542||5073||5064||4923||707|
$ jrecreate.sh --dest cp1 -p compact1
$ jrecreate.sh --dest cp2 -p compact2
$ jrecreate.sh --dest cp2.debug -p compact2 -g -k
$ jrecreate.sh --dest cp2.debug.big --no-compression -p compact2 -g -k
Startup time data (averaged)
|MC Class 4||12.303||12.3||12.392||11.947|
|Tosh Class 10||12.138||12.21||12.369||11.838|
|Sandisk Class 4||11.359||11.366||11.504||11.039|