Java Performance Tuning 2

3.2 Lists

A list is a collection of elements; duplicates are permitted. The following classes implement the java.util.List interface:

1. ArrayList
2. Vector
3. LinkedList

Both ArrayList and Vector are growable arrays that provide constant time random access to its elements. Vector originally appeared in the first release of Java (1.0) while the ArrayList officially appeared in the API in version 1.2. Thus the ArrayList conforms more closely to the Collections API than does the Vector; the Vector was retrofitted to support this functionality. The primary difference between the two is that ArrayList is not synchronized by default while Vector is: if you are running single threaded code against the List, then ArrayList should have better performance. If you want to use an ArrayList in synchronized code, you can make it synchronized with the following code:

List list = Collections.synchronizeList(new ArrayList())

The java.util.LinkedList class differs from the growable array classes in that it is implemented by a linked list.

The difference between the two categories of lists is that growable arrays are required to maintain a specific size that is equal to or greater than the number of elements it contains and when that size is exceeded it must be resized to support the additional elements; this is an expensive operation. By maintaining that additional overhead however, you gain constant time inserts and deletes. Locating an element in the array however is O(N), as potentially all elements will have to be examined. Linked lists, on the other hand, use exactly the amount of memory required to hold its data. As new elements are added to the linked list, new Entry’s are created and positioned appropriately in the list. So if memory is at a premium then linked lists will be a good option, but because of the nature of the underlying data structure, inserts into the list, locating elements, and removing specific elements from the list all take O(N) time.

3.3 Maps and Sorted Maps

Maps maintain key and value pairs; keys are maintained in a Set (hence no duplicates) while values are maintained in a Collection (can be thought of as a List – hence duplicates are permitted). The following classes (that you would use as a data structure in your own code) implement the Map interface:

1. HashMap
2. Hashtable
3. LinkedHashMap
4. TreeMap

As you might guess, the difference between a HashMap, a LinkedHashMap, and a TreeMap is the ordering of its keys. All of the benefits and drawbacks discussed with Sets is applicable here. Hashtable, like Vector, is a byproduct of the initial JDK 1.0 release of the Java API and retrofitted to support the Map interface while HashMap officially appeared with the Collections API in version 1.2. Main differences include Hashtable being by default synchronized while HashMap can be synchronized as follows:

Map map = Collections.synchronizeMap( new HashMap());

The final difference is that HashMap permits null keys and values while Hashtable does not.

4.0 Summary

I hope that this section has inspired you to investigate algorithm analysis further and carefully examine your code, particularly related to loops and nested loops. Finally I encourage you to spend time looking through the Javadoc and more specifically the source code that ships with your JDK to investigate the implementation details of the differing data structures. Be sure that you understand your requirements before you choose the appropriate data structure from the wealth of implementations presented through the Collections API.

5.0 JVM Tuning

5.1 Server Mode

It is recommended that you run all your Coherence JVMs in server mode, by specifying the "-server" on the JVM command line. This allows for a number of performance optimizations for long running applications.

5.2 Sizing the Heap

It is generally recommended that heap sizes be kept at 1GB or below as larger heaps will have a more significant impact on garbage collection times. On 1.5 and higher JVMs larger heaps are reasonable, but will likely require additional GC tuning.

Running with a fixed sized heap will save your JVM from having to grow the heap on demand and will result in improved performance. To specify a fixed size heap use the -Xms and -Xmx JVM options, setting them to the same value. For example:

java -server -Xms1024m -Xmx1024m …

Note that the JVM process will consume more system memory then the specified heap size, for instance a 1GB JVM will consume 1.3GB of memory. This should be taken into consideration when determining the maximum number of JVMs which you will run on a machine. The actual allocated size can be monitored with tools such as top.

5.3 GC Monitoring & Tuning

Frequent garbage collection pauses which are in the range of 100ms or more are likely to have a noticeable impact on network performance. During these pauses a Java application is unable to send or receive packets, and in the case of receiving, the OS buffered packets may be discarded and need to be retransmitted.

Specify "-verbose:gc" or "-Xloggc:" on the JVM command line to monitor the frequency and duration of garbage collection pauses.

Starting with Coherence 3.2 log messages will be generated when one cluster node detects that another cluster node has been unresponsive for a period of time, generally indicating that a target cluster node was in a GC cycle.

The PauseRate indicates the percentage of time for which the node has been considered unresponsive since the stats were last reset. Nodes reported as unresponsive for more then a few percent of their lifetime may be worth investigating for GC tuning.

Leave a Comment

Your email address will not be published.