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!
Training online: Threading Essentials course
Tips March 2005
Get rid of your performance problems and memory leaks!
Get rid of your performance problems and memory leaks!
Back to newsletter 052 contents
Dynamic Delegation (Page last updated November 2004, Added 2005-03-30, Author Lu Jian, Publisher OnJava). Tips:
- From 1.3, the Proxy class was added to java.lang.reflect. It can create a concrete class that implements all of the specified interfaces at runtime, dynamically redirecting all of the method calls defined in the interfaces to an InvocationHandler.
- java.lang.reflect.Proxy objects can be used to monitor and dynamically alter performance characteristics.
- [Article describes extentions that can bypass some limitations of java.lang.reflect.Proxy.]
Java Object Persistence with EJB (Page last updated November 2004, Added 2005-03-30, Author Jeff Hanson, Publisher DevX). Tips:
- When persisting Java objects to a relational database it is essential to map the objects to database columns and records in a manner optimized for speed and efficiency.
- An EJB container handles the bulk of infrastructure-level services for an enterprise beans: Transaction management for the bean: Security for the bean; Persistence of the bean; Remote access to the bean; Lifecycle management of the bean; Database-connection pooling; Instance pooling for the bean.
- EJB types: Message-driven beans receive messages through a callback onMessage() method; stateful session beans maintain state for one client over one session only and are not persisted; stateless session beans should be considered as a brand new instances for each request (and are also not persisted); entity beans which are persisted.
- The transient nature of stateless session beans allows an EJB container to reuse bean instances and therefore, usually optimize the performance of the beans.
- Entity beans are persistent, intended to represent the business logic for an entity existing in persistent storage. They allow shared access - concurrency is handled by the container; have primary keys; and participate in transactions.
- Bean-managed persistence (BMP), requires the programmer to write all code within the entity bean to access the data source, giving more flexibility for higher maintenance costs; With container-managed persistence (CMP) the EJB container handles all database access required by the entity bean - which is lowr maintenance and allows the containers to optimize persistence.
Data structures (Page last updated September 2004, Added 2005-03-30, Author Nick Williams, Publisher IBM). Tips:
- Clearly determine all changes to the code base so that you can find code level changes that cause performance problems.
- Roll back individual changes to identify which is causing a new performance bottleneck.
- Use a profiling tool to identify the source of performance bottlenecks.
- Profiling tools are the only option where performance problems are discovered long after their introduction.
- Daily performance testing is a beneficial improvement.
- The longer a string, the more time it takes to perform an equality check, especially if the strings are only different near the end.
- If you change a string structure so that differences move to the front or shorten the string, you gain minor performance benefits.
- Contention for a lock can become a performance bottleneck.
- A List is potentially a poor choice for a large collection where contains() is being called on the list - a Map is a better structure for such lookups.
- A change to a method which makes it take slightly longer can cause a disproportionately large effect if the method is called within a critical synchronized block.
- Hash-based collections aim to provide efficient insertion and find operations, at the cost of no ordering of the items in the collection and possibly inefficient removal of items from the container.
- The hashCode() method of keys in a hash-based collection should avoid collisions, and preferably spread keys evenly. It should also be quick and easy to compute.
- Adding to the head and tail end of a linked list is quick and inexpensive. Sorting can also be efficient, but retrieving items is potentially expensive, as each node has to be traversed and evaluated.
The Java Async IO Package (Page last updated October 2004, Added 2005-03-30, Author Mike Edwards Tim Ellison, Publisher JavaDeveloperJournal). Tips:
- The Async IO package provides an alternative to the New IO package (java.nio), where performance and scalability are limited by the polling design of the select() method. (com.ibm.io.async, is designed as an extension to the Java 2 Standard Edition 1.4, which can in principle be provided on any hardware and software platform. The platforms currently supported by the package include Windows, AIX, Linux, and Solaris.)
- The existing standard Java facilities for handling network connections and files do not serve the needs of server-side applications adequately.
- The java.io and java.net packages provide synchronous IO capabilities, which require a one-thread-per-IO-connection style of design, which limits scalability since running thousands of threads on a server imposes significant overhead on the operating system.
- The New IO package, java.nio, addresses the scalability issue of the one-thread-per-IO-connection design, but the New IO select() mechanism limits performance.
- The Async IO package makes available fast, scalable IO based on the use of asynchronous notifications of IO operations taking place in the operating system layers to Java applications through a package that provides IO capabilities linked to an asynchronous style of programming.
- [Article describes using the com.ibm.io.async package].
- A test using three server design modes and as much caching as possible shows "old" io limited to about 7,000 threads, "new" io shows increasing overhead from the management of connections, while the async io is reasonably stable. The three server design modes are: Synchronous Server, using the original Java IO classes, one thread per client; New IO Server, using the New IO classes, one thread per CPU; Asynchronous IO Server, using the Async IO package, one thread per CPU;
Bitwise Optimization in Java (Page last updated February 2005, Added 2005-03-30, Author Glen Pepicelli, Publisher OnJava). Tips:
- Avoiding conditionals can often increase performance on modern processors with multiple pipelines.
- "if (x == a) x= b; else x= a;" can be rewritten to avoid the conditional as "x= a ^ b ^ x;"
- Bitsets, which are implemented as integers, can replace arrays in some situations for optimizations.
- The Sun JVM spec says nothing about the relative speed at which the given opcodes are executed. You may spoon-feed the JVM the code you think will run fastest, only to be shocked by lack of improvement or even detrimental effects.
- JVM optimizations, even if they are mainstays in compiled languages, should be benchmarked.
- There are two kinds of memory in every JVM: stack, where local primitives and expressions are stored; and heap, where objects and arrays are stored. The heap is subject to garbage collection, while the stack is a fixed chunk of memory.
- The JVM is really a 32/64-bit machine, so the byte and short primitives are unlikely to run any faster than the int.
- With bit flags, you can stuff a large number of options in a single word, e.g. OPT1=2;OPT2=4;OPT3=8;//opts 1&3 is "OPT1|OPT3".
- Using bit flags your program can pass around a whole group of Boolean variables in no time with a simple assignment expression.
- You can apply fast multi-boolean checking using bit flags: for example if only one of a sequence of options are valid, you can & the expression and only one bit should be in the result (determinable by "if (result != (result & (-result)) ) then Illegal...").
- Bit-parallel expressions can be very powerful and are the key thing to look for in your own projects. If you see a lot of bit-parallel operations, you might have a good candidate for bitwise optimization.
- Bitset optimizations must be considered carefully, they are not always faster.
- In general, bitsets have these pros and cons, Pros: reduced memory usage; fast copy, set, and comparison operations; bit-parallel transformations in fewer operations; Cons: higher maintenance; no atomic access of bits; reduced extensibility; not OOP; not everything falls in their domain, mass calculations work best.
References (Page last updated November 2004, Added 2005-03-30, Author Heinz M. Kabutz, Publisher JavaSpecialists). Tips:
- For 1.3 soft and weak references are released at about the same time, independently of how many references you have.
- For 1.4 and 5.0, weak references are typically released first, and soft references are mainly released when the memory becomes low.
- [Article includes an implementation of SoftHashMap, a SoftReference based HashMap.]
- The big difference between the phantom and weak references are that both are released rather quickly, but the phantom reference is enqueued in the reference queue before it's referent is cleared, whereas the weak reference is enqueued after the referent is cleared. But note the PhantomReference.get() method always returns null.
- If you want a reference to be added to the reference queue, you have to keep a strong reference to the reference.
- [Article implements a GhostReference which is a PhantomReference that does not need a strong reference on it to be enqueued].
Getting High Performance from Your Desktop Client (Page last updated February 2005, Added 2005-03-30, Author Chet Haase, Scott Violet, Edward Ort , Publisher Sun). Tips:
- When using AWT/Swing there are at least two threads: One that is responsible for receiving and processing native events, and the other thread for dispatching these events (the EDT). The native thread immediately fills in the background in gray when it receives an expose event (hence why repaint freezes are gray) and when the event is processed on the EDT the real painting is done, so if your application is busy there can be a noticeable delay between when the gray area is shown and when you actually paint.
- In future (6.0) each window will have a buffer associated with it, so that when an expose event occurs it immediately copies from the back buffer and your application doesn't have to do anything to avoid the gray windows in repaint - you'll never get a gray rectangle, and even if your application is busy.
- 1.4 accelerated fills, lines, and buffer/image copies. The 5.0 release had translucency and text acceleration through the OpenGL rendering pipeline (disabled by default, enabled via -Dsun.java2d.opengl=true). In 6.0 translucency and text (anti-aliased and non-anti-aliased) acceleration are being targeted for Windows Direct3D.
- SizeSequence requires O(N) to process inserts and removes, for JTables with variable-height rows which can make it slow.
- Class loading is not free from a time or memory standpoint, so it's better to consolidate as many listeners as you can into a single class. That said, don't contort your application around this, do what makes the most sense.
- If you want live resize, invoke Toolkit.getDefaultToolkit().setDynamicLayout(true). How responsive this is depends upon your application and the contents of the window being resized. 6.0 may make live resize the default (though not before we tune window resizing).
- There were performance issues with our ImageIO jpeg loader in 1.4 that made it slower than the old Toolkit loader (ImageIcon).
- The openGL rendering pipeline is available on Linux in 5.0, which has pretty huge performance wins, depending on what your application does. However, the gl renderer is not enabled by default (due to robustness and performance issues with various cards/drivers), so you'd have to enable it explicitly (sun.java2d.opengl=true) and try it out on your target platforms to make sure it worked well for you.
- If your application does lots of computations on the event thread, your GUI will suffer slow perceived performance.
- One use of GlassPane is for creating a "ghost" of the Component to be dragged in a Container.
- Hardware acceleration has been enabled since 1.4 (DirectX) and 5.0 (GL).
- Component type should not effect rendering speed. In general use JPanel for containment, and JComponent for custom widgets. Also, watch the value of isOpaque. If you're opaque, make sure you invoke setOpaque(true) or override isOpaque to return true, that will make it so you avoid having to paint the parent during repaints.
- Performance targets for 6.0 include anti-aliased text, translucency, Single Threaded Rendering and faster rewriting the DirectX, GL and D3D.
- If you are scaling images to the same size more than once, scale them once to a temp image and then just call drawImage() on that image, it's much faster than scaling it on the fly each time.
- Try disabling DirectX acceleration on Windows to see if that affects scaling performance (sometimes way faster to do software rendering to a software back buffer than a VRAM back buffer): -Dsun.java2d.ddoffscreen=false.
Back to newsletter 052 contents
Last Updated: 2018-10-29
Copyright © 2000-2018 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