Java Performance Tuning
Java(TM) - see bottom of page
Our valued sponsors who help make this site possible
New Relic: The first free APM tool with production profiler. Download now!
ManageEngine: End-to-End Java Performance Management. Download Product Now!
Download a trial of JProbe, the enterprise-class Java profiler, today.
Newsletter no. 12, November 27th, 2001
|
JProfiler
|
|
Get rid of your performance problems and memory leaks!
|
|
See Your Message Here
|
|
You could have your tool advertised here, to be seen by thousands of potential customers
|
|
New Relic
|
|
New Relic: The first free APM tool with production profiler. Download now!
|
|
ManageEngine
|
|
ManageEngine: End-to-End Java Performance Management. Download Product Now!
|
|
Quest Software
|
|
Download a trial of JProbe, the enterprise-class Java profiler, today.
|
|
JProfiler
|
|
Get rid of your performance problems and memory leaks!
|
|
|
I have often found myself creating collection classes for holding
primitive data types (like int) for performance purposes.
The advantages of avoiding the primitive wrapper classes (e.g. Integer)
and the attendant extra objects, method accesses and casts can be
significant. So I was delighted to hear from Eric Friedman who is
building a free open source library dedicated to implementing
performance optimized collection classes, including collections
which directly support primitive data types. The project, called
Trove, is hosted on sourceforge at
http://trove4j.sourceforge.net.
The usual mixture of articles is missing this month. For the
first time in a while we don't have a games or embedded performance
article. But one on SOAP has appeared, and the enterprise
Java articles (atomic file transactions, RMI) are increasingly
sophisticated.
Kirk continues his airport performance analysis, as well as
his usual succint coverage of the performance discussion groups.
And here's my usual reminder to our Japanese readers that
Yukio Andoh's translation should be available at
http://www.hatena.org/JavaPerformanceTuning/ in a while.
News
Java performance tuning related news.
Upcoming
- From next month I will be categorizing the tips on the website, so summary tips pages on specific subjects will start becoming available.
- I've started extracting tips from Wilson & Kesselman's book (availble online, see the articles/tips below), and I'll carry on with more chapters next month.
Links
Recent Articles
All the following page references have their tips extracted below.
Older Pages
All the following page references have their tips extracted below.
Jack Shirazi
Last month, I commented upon my travel through airports. Since then, there has been a dramatic
increase in the amount of security in place at airports. There has also been about a 20%
reduction in the number of flights as fewer people are flying. How have these changes affected my
travel time? Since we are looking at a reduction in the amount of traffic, one would think
that we should see an overall reduction in my travel time. My experiences so far run counter
to that assumption. To see why, let's divide the system of air travel into three parts; travel
from airport entrance to my seat on the aircraft, travel on the aircraft, and travel from
aircraft door to the airport exit.
The time it takes for me to get from the aircraft door until I exit the airport has not
changed. Due to reduced air traffic, there has been an expected improvement in on-time
performance. But, that reduction only applies to flights that were late. So, the overall
benefit has been negligible. The biggest impact on my travel time has been the amount of time
that it takes me to pass through the airport to the aircraft. So, let's break down that portion
of the system so that we might better understand what is happening.
The biggest change has been the introduction of extra security. This can be seen at check-in,
the x-ray and metal detector screening and during the boarding process, three points of
serialization in this portion of the system. Interestingly enough, the effect of the extra
security check introduced during the check-in and boarding process is negligible. During
check-in, the extra security is carried out as the counter agent is waiting for other tasks to
complete and thus does not result in an increase in service time. The extra check during the
boarding process does add to the service time but since the true bottleneck is people trying to
stuff oversized carry on bags into the undersized overhead, this time is not noticeable. The
biggest effect comes in the serialization point where the increase in service time cannot be
hidden, the x-ray/metal detector screening. The effect of service time on throughput can be
explored using the formula T = 1 / S, where T is the throughput, and S is the service time.
For example, if it normally took about 10 seconds to pass through the metal detector, T = 1 /
10 sec which yields 360 passenger per hour. It now takes about 20 seconds. So, T = 1 / 20 sec
which yields 180 passengers per hour. More complex statistics can be used to predict my
expected time in the queue but the overall effect is that I need to get to the airport earlier.
This month did see an increase in the number of discussions in the saloon at the Java
Ranch. What started out as a discussion on whether initializing object references
improved performance turned into an interesting discussion on garbage collection and local
variable storage. The original question was quickly answered. By default, objects are
initialized to null. Performing this initialization twice is a performance drain.
More interestingly, it was pointed out that even though local variables are declared on the
stack, the data is maintained in the heap. The consequence of this is that all local variables
will be garbage collected when the stack frame goes out of scope.
Another discussion centered on an application that took a significant amount of time to process
a ResultSet from a JDBC call. The JDBC call was returning several tens of thousands of records
from the database. The most interesting point drawn out during the discussion was the fact
that some JDBC drivers will return a ResultSet as soon as some data is available. This may
lead to a situation where the subsequent next() calls will block. This gives the appearance
that the query ran quickly but processing the results was the problem. So, things are not
always as they seem.
A greenhorn asked a question on how best to reuse a StringBuffer. When toString() is called on
a StringBuffer, it passes the underlying char array to the String. Any subsequent changes to
the StringBuffer will force it to create a new char array. Since you cannot control how the
array is created, it is most likely better just to create a new StringBuffer. Reading the
source code for StringBuffer turned out to be invaluable for answering this question.
What are the effects of the serialization points that exist in the systems you work with?
ECPerf is an Enterprise JavaBean benchmark being developed under the Java Community Process
(JCP). Its purpose is to measure the scalability and performance of J2EE servers. It does not
focus on presentation or DBMS scalability. In addition to what can be found at
www.javasoft.com, The Middleware Company lists
several resources at
www.ecperf.theserverside.com/ecperf
pertaining to ECPerf. You can also find additional sources
at www.specbench.org.
A participant was looking for tools to help with his performance testing. Most of the
respondents represented vendors. The following is a list of their offerings.
- Mercury Interactive , LoadRunner, found at http://www-heva.mercuryinteractive.com/.
- Empirix, Bean-test and e-TEST Suite, found at http://www.empirix.com
- IBM/AlphaWorks, Jinsight, found at http://www.ibm.alphaworks.
- Wily Technology, Introscope found at http://www.wilytech.com.
- Performant, Inc., OptiBench, http://www.performant.com
You can find reviews at http://www.nejug.org/reviews.htm.
As is typically the case, the gamers are at the bleeding edge of technology
in their quest to provide us with the best gaming experience possible. Such was the case with
a question regarding the class GatheringByteChannel and buffer classes found in the nio package
in the new jdk1.4. The answer describes a very important difference between direct and
nondirect buffer object. Simply put, direct buffer objects are directly read from and written
to channels. Reads and writes performed on nondirect buffer objects cause data to be copied.
Consequently, nondirect buffers are slower and may generate garbage. The advice: you should
convert nondirect buffers to direct buffers if you will be using them more than once.
Timers are used by games to control the frame rates on the display. Thus they are critical to
the look of a game. Further evidence of how bleeding edge gamers really are is the thread
on timers. The thread starts out complaining about the lack of a high-resolution
reliable timer. The following code fragment was offered as a solution but, the problems were
quickly pointed out and some corrections were offered.
while(true) {
try{
synchronized(this) {
this.notify();
}
Thread.sleep(mydelay);
} catch ( InterruptedException e ) { }
}
The first problem was that sleep time could not always be counted upon. For instance, sleep(4)
== sleep(0) and sleep(5) == sleep(10). Though this difference may look small, if you?re doing
timing related activities, you may experience a significant amount of drift. This lengthy
thread pointed out many other pitfalls and offered many other great recommendations.
Kirk Pepperdine.
http://www.onjava.com/pub/a/onjava/2001/10/23/optimization.html
The RandomAccess interface. (Page last updated October 2001, Added 2001-11-27, Author Jack Shirazi). Tips:
- A java.util.List object which implements RandomAccess should be faster when using List.get() than when using Iterator.next().
- Use
instanceof RandomAccess to test whether to use List.get() or Iterator.next() to traverse a List object.
- [Article describes how to guard the test to support all versions of Java].
http://www.javaworld.com/javaworld/javaqa/2001-11/02-qa-1109-boolean.html
Converting booleans to strings. (Page last updated November 2001, Added 2001-11-27, Author Tony Sintes). Tips:
- Use String.valueOf(bool) to convert booleans to strings.
http://www.onjava.com/pub/a/onjava/2001/11/07/atomic.html
Atomic File Transactions. (Page last updated November 2001, Added 2001-11-27, Author Jonathan Amsterdam). Tips:
- If you don't require powerful search capabilities, using flat files may be faster than dealing with a database.
- Basic file operations (deletion, creation, renaming) are atomic. Other operations and combinations of operations are not atomic. Atomicity can be built but comes at a performance cost. You will have to determine whether the increase in robustness is worth the slowdown in your application.
- Do the I/O in a background thread to mitigate the performance impact of adding atomicity to file transactions.
- [Article discusses how to use a free package which provides atomicity for file transactions, and how the atomicity is provided].
http://www.javaworld.com/javaworld/jw-11-2001/jw-1116-dcl.html
Double-checked locking revisited. (Page last updated November 2001, Added 2001-11-27, Author Brian Goetz). Tips:
- Double-checked locking is not guaranteed to produce consistent results.
- Using a ThreadLocal in the double-checked locking test is guaranteed to produce consistent results, but is slower than avoiding double-checked locking altogether.
- ThreadLocal is faster in each SDK release through 1.2, 1.3 and 1.4. 1.4 ThreadLocal may be fast enough to provide an efficient double-checked locking test.
http://www.onjava.com/pub/a/onjava/2001/10/17/rmi.html
Command objects for RMI. (Page last updated October 2001, Added 2001-11-27, Author William Grosso). Tips:
- Use Command objects to automatically queue or retry RMI calls.
http://www.onjava.com/pub/a/onjava/2001/10/31/rmi.html
Caching RMI stubs. (Page last updated October 2001, Added 2001-11-27, Author William Grosso). Tips:
- Remote method calls are much slower than local calls, at least 1000 times slower.
- Reduce the number of remote calls made by an application to improve performance.
- Cache remote objects locally where possible, rather than repeatedly fetching them.
- Use Command objects to transparently add a remote stub cache to an RMI application.
- Caching stubs keeps them from being garbage collected, and may prevent an RMI server from closing. Use a policy to expire stubs and delete them from the cache.
http://intranetjournal.com/articles/200110/gb_10_24_01a.html
Website performance. (Page last updated October 2001, Added 2001-11-27, Author Gordon Benett). Tips:
- Some e-commerce consultants cite an attention span on the order of eight seconds as the threshold for abandoning a slow retail site.
- Where broadband connections are the norm, pages that don't appear instantly stand a good chance of never being seen: slow pages might as well be no pages.
- Systems can only be designed to meet performance goals if those goals have been identified. Determine what range of response times will be acceptable.
- Try to understand the performance impacts of your design decisions. However the performance of some design choices can be hard to predict and may remain unclear before testing.
- Test the system under conditions that simulate real patterns of use.
- Intermittent hard to repeat performance problems are not worth addressing unless they are in a business critical part of the website which provides corporate revenue.
- Use a rapid, iterative development process in combination with frequent performance testing.
- Try to plan up-front rather than have to rely on late-phase tuning.
http://www-106.ibm.com/developerworks/webservices/library/ws-testsoap/
Scaling SOAP-based web services. (Page last updated November 2001, Added 2001-11-27, Author Frank Cohen). Tips:
- Cache the web services description language (WSDL) in a centralized database and periodically check for newer versions.
- Cache schema definitions for scalability.
- Use simple SOAP data types (String, Int, Float, NegativeInteger).
- Each new data type introduces a serializer to convert from the XML value into a Java value and back again, which may cause performance problems.
- SOAP messages move much more data than the average HTTP GET or POST call, adversely impacting network performance.
- Transactional SOAP calls need to cache the state of sessions.
- [Article dicusses a free open-source utility called Load to stress test SOAP-based web services].
http://java.sun.com/docs/books/performance/1st_edition/html/JPPerformance.fm.html
Chapter 1, "What Is Performance?" of "Java Platform Performance". (Page last updated 2000, Added 2001-11-27, Author Steve Wilson and Jeff Kesselman). Tips:
- Design your software with the target configuration (e.g. RAM) in mind.
- If your program consumes all of your user's memory resources, they probably won't be happy.
- Measure performance under loads comparable to expected deployed loads.
- Perceived performance is a highly important aspect of performance. How fast a program feels is more important than how fast it really is.
http://java.sun.com/docs/books/performance/1st_edition/html/JPProcess.fm.html
Chapter 2, "The Performance Process" of "Java Platform Performance". (Page last updated 2000, Added 2001-11-27, Author Steve Wilson and Jeff Kesselman). Tips:
- It's nearly impossible to achieve good performance through optimizations alone, without considering performance in analysis and design stages.
- Creating clear system and performance requirements is the key to evaluating the success of your project.
- Use cases provide excellent specifications for building benchmarks.
- Specify the limitations of the application: well-defined boundaries on the application scope can provide big optimization opportunities.
- Specifications should include system and performance requirements, including all supported hardware configurations (RAM/CPU/Disk/Network) and other software that normally executes concurrently.
- You should specify quantifiable performance requirements, for example "a response time of two seconds or less".
- Scalability is more dependent on good design decisions than optimal coding techniques.
- Encapsulation leads to slowdowns from increased levels of indirection, but is essential in large, scalable, high-performance systems. For example, using a java.util.List object may be slower than using a raw array, but allows you to change very easily from ArrayList to LinkedList when that is faster.
- Meeting or exceeding your performance requirements should be part of the shipping criteria for your product.
- Once you've determined that a performance problem exists, you need to begin profiling. Profilers are most useful for identifying computational performance and RAM footprint issues.
- Performance tuning is an iterative process. Data gathered during profiling needs to be fed back into the development process.
http://java.sun.com/docs/books/performance/1st_edition/html/JPMeasurement.fm.html
Chapter 3, "Measurement Is Everything" of "Java Platform Performance". (Page last updated 2000, Added 2001-11-27, Author Steve Wilson and Jeff Kesselman). Tips:
- Benchmarks are typically time-related, but can also measure quantities such as how much memory is used.
- A stopwatch is a versatile benchmarking tool.
- System.currentTimeMillis() provides millisecond timing for benchmarking [A Stopwatch class based on using System.currentTimeMillis() is presented].
- Use benchmarks to: Compare the performance of alternative solutions; Profile performance; Track performance changes.
- Micro-benchmarks (repeatable sections of code) can be useful but may not represent real-world behavior. Factors that can skew micro-benchmark performance include Java virtual machine warm-up time, and global code interactions.
- Macro-benchmarks (repeatable test sequences from the user point of view) test your system as actual end users will see it.
- Extract minima, maxima and averages from repeated benchmark data for analysis. Use these to compare progress of benchmarks during tuning. [I like to add the 90th-centile value too].
- Profilers help you find bottlenecks in applications, and should show: the methods called most often; the methods using the largest percentage of time; the methods calling the most-used methods; and the methods allocating a lot of memory.
- The Sun JVM comes with the hprof profiler.
- Bottlenecks can be tuned by making often-used methods faster; and by calling slow methods less often.
- Backtrace methods to understand the context of the bottleneck. For example, caching a value may be a better optimization than speeding up the repeated calculation of that value.
- Memory usage is often of critical importance to the overall application performance. Excessive memory allocation is often one of the first things that an experienced developer looks for when tuning a Java program.
- Examine bottlenecks for memory allocation. For example you may be able to replace a repeated object allocation in a loop with a reusable object allocated once outside the loop.
- Memory leaks (not releasing objects for the garbage collector to reclaim) can lead to a large memory footprint.
- You identify memory leaks by: determining that there is a leak; then identifying the objects that are not being garbage colleted; then tracing the references to those leaking objects to determine what is holding them in memory.
- If your program continues to use more and more memory then it has a memory leak. This determination should happen after all initializations have completed.
- Identify memory leak objects by marking/listing the objects in some known state, then cycling through other states and back to that known state and seeing which extra objects are now present.
- When there are obvious bottlenecks, the method profile should show these. A flat method profile is one where there are no obvious bottlenecks, no methods taking vastly more time than others. In this case you should look at cumulative method profiles, which show the relative times taken by a method and all the methods it calls (the call tree). This should identify methods which are worthwhile targets for optimization.
Jack Shirazi
Last Updated: 2010-09-01
Copyright © 2000-2010 Fasterj.com. All Rights Reserved.
All trademarks and registered trademarks appearing on JavaPerformanceTuning.com are the property of their respective owners.
Java is a trademark or registered trademark of Sun Microsystems, Inc. in the United States and other countries. JavaPerformanceTuning.com is not connected to Sun Microsystems, Inc. and is not sponsored by Sun Microsystems, Inc.
URL: http://www.JavaPerformanceTuning.com/newsletter012.shtml
RSS Feed: http://www.JavaPerformanceTuning.com/newsletters.rss
Trouble with this page? Please contact us