Java Performance Tuning
Java(TM) - see bottom of page
Our valued sponsors who help make this site possible
JProfiler: Get rid of your performance problems and memory leaks!
Newsletter no. 2, January 19th, 2001
Get rid of your performance problems and memory leaks!
Get rid of your performance problems and memory leaks!
This month, there is a definite server based flavor to the
articles I've added to my site. Several of the recently
published performance articles are server focused. And my
search backlog coincidentally also threw up some server
related pages including several IBM papers on tuning Java
in WebSphere, which provide useful generic server-Java tuning
tips. (Note that apart from my book, all product related
listings are for your information, and should not be
considered as an approval or disapproval of that product.
I do recommend my book, of course.)
For those of you with any experience in developing server
cores (the underlying server framework, not EJBs etc.), you
may be delighted to hear about Matt Welsh's non-blocking
I/O library. This uses the JNI to give access to the
select(2)/poll(2) system call, allowing efficient
multiplexing of multiple i/o streams without using a
thread per stream.
Finally, this month Kirk Pepperdine starts a useful roundup
of Java performance discussion groups.
I haven't had time to extract the tips from these two yet.
All the following page references have their tips extracted below.
Articles, papers & packages less than six months old
New from us
My colleague Kirk Pepperdine will be producing his own idiosyncratic
roundup of some of the interesting discussions from the various Java
performance discussion groups. We currently know of the two at
TheServerSide and JavaRanch. If you know of any other Java
performance discussion groups, please let us know (mail us from
Kirks article follows just below.
Other additions to the website
I've extracted the tips from even more pages beyond those
listed above, and I've also listed some interesting performance
reports and a couple more tools.
When I first pointed my browser at http://www.javaranch.com, "What?"
I couldn?t help but thinking, "What is this?. The theme is corny
but they are offering a chance to win a book." So, I dutifully filled
out the registration form and then started to browse. The topic in the
performance forum, "Most common costliest Elements of Java", looked
interesting and there were a number of responses so, I clicked in.
Although the question seemed fairly ordinary, the responses clearly
demonstrated that this site was anything but corny. A quick summary
of the thread would be: "object creation, casting, synchronization
and exceptions are the most costly elements of Java". Of the four,
I will focus here on exceptions.
The performance impact of using Exceptions is becoming better known.
What is not so well known is why Exceptions degrade performance. In
the discussion, Peter Haggar does a masterful job of explaining
what happens when you create and throw an exception. The cost of
using exception shows up in several ways.
First, throwing an exception means that you?ve just created a new
object. But, as Peter points out, the constructor in Throwable calls the
native method, fillInStackTrace(). This method walks the stack frame
collecting trace information. Peter then goes on to point out that
using exceptions requires extra bytecodes. Using exceptions requires
an additional table in the class file. Throwing an exception disrupts
the normal flow of the execution in the JVM. The JVM must take the
costly step of fixing the call stack when an exception is thrown.
In the end Peter quite rightfully points out that you should "use
exceptions for error conditions, not for control flow."
The density of usable information on this discussion group makes it a
very worthwhile trip. I look forward to reviewing this group and others
for future editions of this newsletter.
Some performance tips (Page last updated January 2001, Added 2001-01-19, Author Shyam Lingegowda). Tips:
- Use buffering for files & stream i/o . Use byte streams (not char-streams) for ASCII characters.
- Recycle objects wherever possible.
- Factor out constant computations from loops. For Servlets, push one time computations into the init() method.
- Use StringBuffer when dealing with mutable strings. Initialize the StringBuffer with proper size.
- Let the compiler do compile time string concatenation.
- Comparison of two string objects is faster if they differ in length.
- StringTokenizer is slow.
- minimize the number of objects you create.
- Avoid initializing twice.
- Order boolean expressions so that they execute as fast as possible.
- ArrayList is faster than Vector.
- Minimize calls to Date and related classes.
Good Java practices, some of which are good for performance. This page has already been listed on the Tuning Tips page, and the following tips are new items that have been added to the page since it was last listed (Page last updated January 2001, Added 2001-01-19, Author Dave Jarvis). Tips:
- Always profile the code to find where the bottlenecks are.
- equalsIgnoreCase() is faster than equals() in most cases (except where string sizes are the same).
- Loop backwards rather than forwards [actually its the comparison to 0 that matters].
- Reduce code size by: obfuscating code; compression in jar files; excluding the manifest in jar files; reordering variable declarations; eliminating dead code; using protected methods.
Detailed article on load testing systems (Page last updated January 2001, Added 2001-01-19, Author Himanshu Bhatt). Tips:
- Internet systems should be load-tested throughout development.
- Load testing can provide the basis for: Comparing varying architectural approaches; Performance tuning; Capacity planning.
- Initially you should identify the probable performance and scalability based on the requirements. You should be asking about: numbers of users/components; component interactions; throughput and transaction rates; performance requirements.
- Factor in batch requirements and performance characteristics of dependent (sub)systems. Note that additional layers, like security, add overheads to performance.
- Logging and stateful EJB can degrade performance.
- After the initial identification phase, the target should be for a model architecture that can be load-tested to feedback information.
- Scalability hotspots are more likely to exist in the tiers that are shared across multiple client sessions.
- Performance measurements should be from presentation start to presentation completion, i.e. user clicks button (start) and information is displayed (completion).
- Use load-test suites and frameworks to perform repeatable load testing.
Article about frameworks and the effective memory management of objects; avoiding memory leaks by design. (Page last updated January 2001, Added 2001-01-19, Author Leonard Slipp). Tips:
- Define the life cycles of objects and the duration of object interrelationships. Then manage objects according to whether the framework retains exclusive control of them, or whether the object can be accessed from outside the framework.
- Minimize the number of objects that can be accessed from outside the framework.
- In general, the creator of an object should be responsible for the objects' life cycle. Where this is not the case, the transfer of ownership of the object should be explicit and emphasized. Similarly object relationship management should be explicit and reversible: for every add() action, there must be a remove(); for every register() action, there must be a deregister().
Article on using syslog to track performance across distributed systems (Page last updated December 2000, Added 2001-01-19, Author Brian Maso ). Tips:
- Use syslog to log distributed system performance.
- Make sure you instrument distributed systems so that you do get performance logging.
"EJB2 clustering with application servers" (Page last updated December 2000, Added 2001-01-19, Author Tyler Jewell). Tips:
- [Article discusses multiple independent ways to load balance EJBs]
Sun community chat session with Bill Shannon, Kevin Osborn, and Jim Glennon on JavaMail (Page last updated December 2000, Added 2001-01-19, Author Edward Ort). Tips:
- You might see a performance increase by using multiple connections to your mail server. You would need to get multiple Transport objects and call connect and sendMessage on each of them, using multiple threads (one per connection) in your application.
- JavaMail 1.2 includes the ability to set timeouts for the initial connection attempt to the server.
- JavaMail tries to allow you to make good and efficient use of the IMAP protocol. Fetch profiles are one technique to allow you to get batches of information from the server all at once, instead of single pieces on demand. Used properly, this can make quite a difference in your performance.
Whoopee!! A non-blocking I/O library for Java. This is the single most important functionality missing from the SDK for scalable server applications. The important class is SelectSet which allows you to multiplex all your i/o streams. If you want a scalable server and can use this class then DO SO. (Page last updated November 2000, Added 2001-01-19, Author Matt Welsh). Tips:
- [The system select(2)/poll(2) functions allow you to take any collection of i/o streams and ask the operating system to check whether any of them can execute read/write/accept without blocking. The system call will block if requested until any one of the i/o streams is ready to execute. Before Java, no self-respecting server would sit on multiple threads in blocked i/o mode, wasting thread resources: instead select/poll would have been used.]
Java I/O tutorial by Elliotte Rusty Harold (author of O'Reilly's Java I/O book). (Page last updated November 2000, Added 2001-01-19, Author Elliotte Rusty Harold). Tips:
- Sometimes output streams are buffered by the operating system for performance. The flush() method forces the data to be written whether or not the buffer is full. This is not the same as the buffering performed by a BufferedOutputStream. That buffering is handled by the Java runtime. This buffering is at the native OS level. However, a call to flush() should empty both buffers
- It's more efficient to read multiple bytes at a time, i.e use read(byte) rather than read().
- The best size for the buffer is highly platform dependent and generally related to the block size of the disk, at least for file streams. Less than 512 bytes is probably too little and more than 4096 bytes is probably too much. Ideally you want an integral multiple of the block size of the disk. However, you should use smaller buffer sizes for unreliable network connections.
Article on using smart proxies. (Page last updated November 2000, Added 2001-01-19, Author M. Jeff Wilson). Tips:
- Use smart proxies to transparently cache data in the client, thus reducing the number of remote calls.
- Use this approach for caching frequently read, seldom-updated data of remote objects.
- Use smart proxies to monitor the performance of RMI calls.
- Use smart proxies to prevent returning multiple copies of the same remote object to client code.
Hans Bergsten's top ten JSP tips (Page last updated November 2000, Added 2001-01-19, Author Hans Bergsten). Tips:
- The include directive (<%@ include file="filename.inc" %>) is faster than the include action (<jsp:include page="pagename.jsp" flush="true"/>).
- redirects are slower than forwards because the browser has to make a new request.
- Database access is typically very expensive in terms of server resources. Use a connection pool to share database connections efficiently between all requests, but don't use the JDBC ResultSet object itself as the cache object.
Paper detailing the "Best Practices for Developing High Performance Web and Enterprise Applications" using IBM's WebSphere. All the tips are generally applicable to servlet/EJB development, as well as other types of server development. (Page last updated September 2000, Added 2001-01-19, Author Harvey W. Gunther). Tips:
- Do not store large object graphs in javax.servlet.http.HttpSession. Servlets may need to serialize and deserialize HttpSession objects for persistent sessions, and making them large produces a large serialization overhead.
- Use the tag "<%@ page session="false"%>" to avoid creating HttpSessions in JSPs.
- Minimize synchronization in Servlets to avoid multiple execution threads becoming effectively single-threaded.
- Do not use javax.servlet.SingleThreadModel.
- Use JDBC connection pooling, release JDBC resources when done, and reuse datasources for JDBC connections.
- Use the HttpServlet Init method to perform expensive operations that need only be done once.
- Minimize use of System.out.println.
- Avoid String concatenation "+=".
- Access entity beans from session beans, not from client or servlet code.
- Reuse EJB homes.
- Use Read-Only methods where appropriate in entity-beans to avoid unnecessary invocations to store.
- Use the lowest impact transaction level possible for each transaction.
- The EJB "remote programming" model always assumes EJB calls are remote, even where this is not so. Where calls are actually local to the same JVM, try to use calling mechanisms that avoid the remote call.
- Remove stateful session beans (and any other unneeded objects) when finished with, to avoid extra overheads in case the container needs to be passivated.
- Beans.instantiate() incurs a filesystem check to create new bean instances. Use "new" to avoid this overhead.
Tuning IBM's WebSphere product. White paper: "Methodology for Production Performance Tuning". Only non-product specific Java tips have been extracted here. (Page last updated September 2000, Added 2001-01-19, Author Gennaro (Jerry) Cuomo). Tips:
- A size restricted queue (closed queue) allows system resources to be more tightly managed than an open queue.
- The network provides a front-end queue. A server should be configured to use the network queue as its bottleneck, i.e. only accept a request from the network when there are sufficient resources to process the request. This reduces the load on an app server. However, sufficient requests should be accepted to ensure that the app server is working at maximum capacity, i.e. try not to let a component sit idle while there are still requests that can be accepted even if other components are fully worked.
- Try to balance the workload of the various components.
- [Paper shows a nice throughput curve giving recommended scaling behavior for an server]
- The desirable target bottleneck is the CPU, i.e. a server should be tuned until the CPU is the remaining bottleneck. Adding CPUs is a simple remedy to this.
- Use connection pools and cached prepared statements for database access.
- Object memory management is particularly important for server applications. Typically garbage collection could take between 5% and 20% of the server execution time. Garbage collection statistics provide a useful monitor to determine the server's "health". Use the verbosegc flag to collect basic GC statistics.
- GC statistcs to monitor are: total time spent in GC (target less than 15% of execution time); average time per GC; average memory collected per GC; average objects collected per GC.
- For long lived server processes it is particularly important to eliminate memory leaks (references retained to objects and never released).
- Use -ms and -mx to tune the JVM heap. Bigger means more space but GC takes longer. Use the GC statistics to determine the optimal setting, i.e the setting which provides the minimum average overhead from GC.
- The ability to reload classes is typically achieved by testing a filesystem timestamp. This check should be done at set intermediate periods, and not on every request as the filesystem check is an expensive operation.
Sun community chat session with Steve Wilson and Jeff Kesselman on Java Performance (Page last updated August 2000, Added 2001-01-19, Author Edward Ort). Tips:
- HotSpot JVMs can return heap memory to the OS while running.
- HotSpot Client VM (JVM 1.3) is optimized for quick startup time and low-memory footprint. The server VM (HotSpot 1.0/2.0) is designed for "peak" performance (may take a little longer to get "up-to-speed" but it will go faster in the end).
- Always use System.arraycopy to copy arrays.
- Sticky applets available with the 1.3 plugin speeds startup (persistently caches classes on clients). Also put resources together into jar file to reduce download requests.
- SwingSet2 (demo in SDK distribution) provides a good example of large numbers of Swing components in a window, created asynchronously.
- Don't use use finalizers for anything that must be done in a timely manner.
- Use primitives and transients to speed up serialization.
- Use a concentrator object to limit the repaint events to once every 100 milliseconds in heavily loaded systems and in multi-threaded swing environments. There is some overhead for context switching (using invokeLater) into the AWT-event thread, which you want to minimize.
- The key to high performance code is organization and process. Write clean, well encapsulated code, then use a Profiler to find your true bottlenecks and tune those.
Peter Haggar's Practical Java Programming Language Guide. (Page last updated 2000, Added 2001-01-19, Author Peter Haggar). Tips:
- Focus initially on design, data structures, and algorithms.
- Do not rely on compile-time code optimization.
- Understand runtime code optimization.
- Use StringBuffer, rather than String, for concatenation.
- Minimize the cost of object creation.
- Guard against unused objects.
- Minimize synchronization.
- Use stack variables whenever possible.
- Use static, final, and private methods to allow inlining.
- Initialize instance variables only once.
- Use primitive types for faster and smaller code.
- Do not use an Enumeration or an Iterator to traverse a Vector.
- Use System.arraycopy for copying arrays.
- Prefer an array to a Vector or ArrayList.
- Reuse objects whenever possible.
- Use lazy evaluation.
- Optimize source code by hand.
- Compile to native code.
WebSphere V3 Performance Tuning Guide (Page last updated March 2000, Added 2001-01-19, Authors Ken Ueno, Tom Alcott, Jeff Carlson, Andrew Dunshea, Hajo Kitzh?fer, Yuko Hayakawa, Frank Mogus, Colin D. Wordsworth). Tips:
- [The Red book lists and discusses tuning parameters available to Websphere]
- Run an application server and any database servers on separate server machines.
- JVM heap size: -mx, -ms [-Xmx, -Xms]. As a starting point for a server based on a single JVM, consider setting the maximum heap size to 1/4 the total physical memory on the server and setting the minimum to 1/2 of the maximum. Sun recommends that ms be set to somewhere between 1/10 and 1/4 of the mx setting. They do not recommend setting ms and mx to be the same. Bigger is not always better for heap size. In general increasing the size of the Java heap improves throughput to the point where the heap no longer resides in physical memory. Once the heap begins swapping to disk, Java performance drastically suffers. Therefore, the mx heap setting should be set small enough to contain the heap within physical memory. Also, large heaps can take several seconds to fill up, so garbage collection occurs less frequently which means that pause times due to GC will increase. Use verbosegc to help determine the optimum size that minimizes overall GC.
- In some cases turning off asynchronous garbage collection ("-noasyncgc", not always available to all JVMs) can improve performance.
- Setting the JVM stack and native thread stack size (-oss and -ss) too large (e.g. greater than 2MB) can significantly degrade performance.
- When security is enabled (e.g. SSL, password authentication, security contexts and access lists, encryption, etc) performance is degraded by significant amounts.
- One of the most time-consuming procedures of a database application is establishing a connection to the database. Use connection pooling to minimize this overhead.
Practical Java Programming Language Guide by Peter Haggar. This book includes a good-size section on performance. The Praxis list from that section is on the Tuning Tips page.
A "we're great and they suck" performance comparison by IBM of IBM WebSphere vs. Microsoft IIS.
Non-technical article with basic performance comparisons of some leading application servers (Page last updated November 2000, Added 2001-01-19, Author Rich Seeley). Tips:
Steven Meloan's in depth look at the HotSpot Performance Engine (June 1999)
The Java Performance Report, Part III from September 2, 2000, by Osvaldo Pinali Doederlein. If you are still looking for comparitive performance reports (JVM vs JVM, Java vs C), this is pretty useful.
WebSphere Studio Page Detailer
TowerJ Application Performance Analyzer
Last Updated: 2017-10-01
Copyright © 2000-2017 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 Oracle Corporation in the United States and other countries. JavaPerformanceTuning.com is not connected to Oracle Corporation and is not sponsored by Oracle Corporation.
RSS Feed: http://www.JavaPerformanceTuning.com/newsletters.rss
Trouble with this page? Please contact us