Smart object-management saves the
day - JavaWorld November 1999
Tutorial Details:
Java performance programming, Part 1: Smart object-management saves the day
Java performance programming, Part 1: Smart object-management saves the day
By: By Dennis M. Sosnoski
Learn how to reduce program overhead and improve performance by controlling object creation and garbage collection
bjects are a powerful software engineering construct, and Java uses them extensively. In fact, it encourages the use of objects so much that developers sometimes forget the costs behind the construct. The result can be object churn, a program state in which most of your processor time is soaked up by repeatedly creating and then garbage collecting objects.
Java performance programming: Read the whole series!
Part 1. Learn how to reduce program overhead and improve performance by controlling object creation and garbage collection
Part 2. Reduce overhead and execution errors through type-safe code
Part 3. See how collectionsalternatives measure up in performance, and find out how to get the most out of each type
This is the first in a series of articles focused on performance issues in Java. In this series, we'll examine a number of areas in which Java performance can be less than ideal, and provide techniques for bypassing many of these performance roadblocks. Actual timing measurements will be used throughout to demonstrate the performance improvements possible with the right coding techniques.
This month, we'll take a look at the issue of object management in Java. Since Java is often in competition with C/C++ as a language choice for implementing applications, we'll start out by reviewing the differences in how these languages manage the allocation and deallocation of objects, and examine what impact these differences have on performance. In the remainder of the article, we'll look at three ways to reduce the amount of object churn in your Java programs.
Java memory management
Java's simplified memory management is one of the key features that appeals to developers with backgrounds in languages such as C/C++. In contrast with the explicit deallocation required by C/C++, Java lets you allocate objects as necessary and trust that they'll be reclaimed and recycled by the JVM when they're no longer needed. The work required to make this happen goes on behind the scenes, in the garbage collection process.
Garbage collection has been used for memory management in programming languages dating back to the dawn of the computer era in the 1960s. The basic principle of garbage collection is the same in all cases: identify objects that are no longer in use by the program, and recycle the memory used by these objects to create new ones.
JVMs generally use a reachability analysis to identify the objects that are in use, then recycle all the other objects. This starts with a base set of variables that the program uses directly, including object references in local or argument variables on the method call stack of every active thread, and in static variables of loaded classes. Each object that one of these variables references is added to the set of reachable objects. Next, each object that a member variable references in one of these objects is also added to the reachable set. This process continues until closure is obtained; in the end, every object referenced by any object in the reachable set is also in the reachable set. Any objects that are not in the reachable set are by definition not in use by the program, so they can safely be recycled.
The developer generally doesn't need to be directly involved in this garbage collection process. Objects drop out of the reachable set and become eligible for recycling as they're replaced with other objects, or as methods return and their variables are dropped from the calling thread's stack. The JVM runs garbage collection periodically, either when it can, because the program threads are waiting for some external event, or when it needs to, because it's run out of memory for creating new objects. Despite the automatic nature of the process, it's important to understand that it's going on, because it can be a significant part of the overhead of Java programs.
Besides the time overhead of garbage collection, there's also a significant space overhead for objects in Java. The JVM adds internal information to each allocated object to help in the garbage collection process. It also adds other information required by the Java language definition, which is needed in order to implement such features as the ability to synchronize on any object. When the storage used internally by the JVM for each object is included in the size of the object, small objects may be substantially larger than their C/C++ counterparts. Table 1 shows the user-accessible content size and actual object memory size measurements for several simple objects on various JVMs, illustrating the memory overhead added by the JVMs.
Table 1. Measured memory usage (bytes)
Content (bytes)
JRE 1.1.8 (Sun)
JRE 1.1.8 (IBM)
JRE 1.2.2 (Classic)
JRE 1.2.2 (HotSpot 2.0 beta)
java.lang.Object
0
26
31
28
18
java.lang.Integer
4
26
31
28
26
int[0]
4 (length)
26
31
28
26
java.lang.String
(4 characters)
8 + 4
58
63
60
58
This space overhead is a per object value, so the percentage of overhead decreases with larger objects. It can lead to some unpleasant surprises when you're working with large numbers of small objects, though -- a program juggling a million Integer s will have most systems down on their knees, for example!
Comparison with C/C++
For most operations, Java performance is now within a few percent of C/C++. The just-in-time (JIT) compilers included with most JVMs convert Java byte codes to native code with amazing efficiency, and in the latest generation (represented by IBM's JVM and Sun's HotSpot) they're showing the potential to start beating C/C++ performance for computational (CPU intensive) applications.
However, Java performance can suffer by comparison with C/C++ when many objects are being created and discarded. This is due to several factors, including initialization time for the added overhead information, garbage collection time, and structural differences between the languages. Table 2 shows the impact these factors can have on program performance, comparing C/C++ and Java versions of code repeatedly allocating and freeing arrays of byte values.
Table 2. Memory management performance (time in seconds)
JRE 1.1.8 (Sun)
JRE 1.1.8 (IBM)
JRE 1.2.2 (Classic)
JRE 1.2.2 (HotSpot 2.0 beta)
C++
Short-term Allocations (7.5 M blocks, 331 MB)
30
22
26
14
9
Long-term Allocations (7.6 M blocks, 334 MB)
48
28
39
33
13
For both short- and long-term allocations, the C++ program is considerably faster than the Java program running on any JVM. Short-term allocations have been one focus area for optimization in HotSpot. Results show that -- with the Server 2.0 beta used in this test -- this is the closest any JVM comes to the C++ code, with a 50 percent longer test time. For long-term allocations, the IBM JVM gives better performance than the HotSpot JVM, but both trail far behind the performance of the C++ code for this type of operation.
Even the relatively good performance of HotSpot on short-term allocations is not necessarily a cause for joy. In general, C++ programs tend to allocate short-lived objects on the stack, which would give a lower overhead than the explicit allocation and deallocation used in this test. C++ also has a big advantage in the way it allocates composite objects, using a single block of memory for the combined entity. In Java, each object needs to be allocated by its own block.
We'll certainly see more performance improvements for object allocation as vendors continue to work on their VMs. Given the above advantages, though, it seems unlikely the performance will ever match C++ in this area.
Does this mean your Java programs are eternally doomed to sluggish performance? Not at all -- object creation and recycling is just one aspect of program performance, and, providing you're sensible about creating objects in heavily used code, it's easy to avoid the object churn cycle! In the remainder of this article we'll look at ways to keep your programs out of the churn by reducing unnecessary object creation.
Keep it primitive
Probably the easiest way to reduce object creation in your programs is by using primitive types in place of objects. This approach doesn't apply very often -- usually there's a good reason for making something an object in the first place, and just replacing it with a primitive type is not going to fill the same design function. In the cases where this technique does apply, though, it can eliminate a lot of overhead.
The primitive types in Java are boolean , byte , char , double , float , int , long , and short . When you create a variable of one of these types, there is no object creation overhead, and no garbage collection overhead when you're done using it. Instead, the JVM allocates the variable directly on the stack (if it's a local method variable) or within the memory used for the containing object (if it's a member variable).
Java defines wrappers for each of these primitive types, which can sometimes confuse Java novices. The wrapper classes represent immutable values of the corresponding primitive types. They allow you to treat values of a primitive type as objects, and are very useful when you need to work with generic values that may be of any type. For instance, the standard Java class libraries define the java.util.Vector , java.util.Stack , and java.util.Hashtable classes for working with object collections. Wrapper classes provide a way to use these utility classes with values of primitive types (not necessarily a good approach from the performance standpoint, for reasons we'll cover in the next article in this series, but a quick and easy way to handle some common needs).
Except for such special cases, you're best o
Read
Tutorial at: Click here to view the tutorial
Rate Tutorial: Smart object-management saves the
day - JavaWorld November 1999
View Tutorial: Smart object-management saves the
day - JavaWorld November 1999
Related
Tutorials:
3D graphics programming in
Java, Part 3: OpenGL
3D graphics programming in
Java, Part 3: OpenGL |
Scripting power
saves the day
for your Java
apps
Scripting power
saves the day
for your Java
apps |
XSLT blooms with
Java
XSLT blooms with
Java |
Jini's relevance emerges, Part
2
Jini's relevance emerges, Part
2 |
J2SE 1.4
breathes new life into the CORBA community, Part
1
J2SE 1.4
breathes new life into the CORBA community, Part
1 |
Check out three
collections libraries
Check out three
collections libraries |
Welcome to the WfMOpen project
WfMOpen is a J2EE based implementation of a workflow facility (workflow engine) as proposed by the Workflow Management Coalition (WfMC) and the Object Management Group (OMG). |
High-availability mobile applications
High-availability mobile applications |
Smart Value Object goes
one step further
Smart Value Object goes one step further
The Smart Value Object allows server components to track client-side modification of business objects in a rich client/J2EE server environment, by using the latest features offered by bytecode processing tools.
|
Ganymede
A log4j plugin to Eclipse that works similar to chainsaw (SocketServer). Includes color, filtering, detailed information, and saves settings. |
JXMLPad 2.3
JXMLPad 2.3
JXMLPad is a pure Swing java component/framework for editing XML/XHTML document.
|
CalendarComponent
Java Calendar Component V 1.0
|
Java Calendar Component
Java date picker component, ready to use in your Swing applications featuring. |
JLisa - A Rule Engine for Java
JLisa is a powerful framework for building business rules accessible to Java and it is compatible with JSR94 V, the JavaTM Rule Engine API
JLisa is more powerful than Clips because it has the expanded benefit of having all the features from common lisp a |
JXMLPad 3.1 FC
JXMLPad is a pure Swing java component/framework for editing XML/XHTML document. |
The SATSA Developer's Guide
Describes how to use the SATSA APIs in MIDP applications. It includes lucid explanations and example code that illustrate how to communicate with a smart card and how to use cryptographic services. It is based on the SATSA Reference Implementation 1.0. |
J2ME Technology Turns 5!
In 2004 the Java 2 Platform, Micro Edition (J2ME) celebrated its fifth anniversary. This article presents where J2ME is today. |
istory of Bioinformatics
istory of Bioinformatics
History of Bioinformatics
The Modern bioinformatics is can be classified into two broad categories, Bi ological Science and computational Science . Here is the data of hi storical events for both biology and computer |
Techniques used for Generating Dynamic Content Using Java Servlets.
Techniques used for Generating Dynamic Content Using Java Servlets.
Techniques used for Generating Dynamic Content
Common Gateway Interface (CGI)
For any web application high performance and timely delivery are key ingredients to competitive |
Enhance your end-user MDI experience with JExplose
Enhance your end-user MDI experience with *JExplose* ! Extremely simple to integrate with your existing Swing MDI products. |
|
|
|