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: Concurrency, Threading, GC, Advanced Java and more ...
Newsletter no. 16, March 25th, 2002
JProfiler
|
Get rid of your performance problems and memory leaks!
|
JProfiler
|
Get rid of your performance problems and memory leaks!
|
|
|
Thanks for those of you who have already voted for my book
"Java Performance Tuning" in the
JDJ readers choice awards.
To those of you who find the JavaPerformanceTuning.com website
useful and haven't yet voted, I encourage you to vote for my book.
The JavaPerformanceTuning.com website is a companion to, and a direct
consequence of my book.
If anyone is interested, I'll be giving a talk in London, UK, on April 18th,
on managing J2EE performance. You need to
register if you feel like coming along. But I understand places are filling up
quickly so don't leave it too late to register.
Now, on to this month's news. I've added 4 new category pages to the website:
tips about using final
;
tips about EJBs and a sub-page for those
tips relating to EJB design; and
tips for those creating webservices.
This month we list a flurry of articles on low-level tuning
(microtuning, GC/heap, string, I/O, and more), a variety of J2EE
tuning articles, mainly EJB but also JTS and JMS. We list more
J2ME articles; a comeback for graphics programming tips, the first
for a couple months; and many more articles.
New articles are still appearing at such a rate that I have no time
at all to get to my backlog of older articles. I've even had to put
some current tutorials into my backlog. A couple of months ago I
delivered a newletter where I characterized the month as belonging
to design patterns. One thing I find interesting is that several of
the articles this month are not about design patterns but include
them almost offhand. Even though design patterns have been around for
years now, two months ago articles mentioning design patterns still
felt the need to explain what they are. Now just a couple of months
later, the articles assume you know the basics, and almost in passing
mention which pattern is being used and what its functionality is.
Kirk discusses load balancing, as well as continuing his usual
excellent roundup of the interesting performance discussions over
the last month. This month, Kirk includes discussions from a new
Java performance discussion list at javadevtalk.
Also this month a new columnist, Javva The Hutt, joins us to talk
about performance related matters. Any relation to the similarly
named Star Wars character is, I am assured, entirely non-coincidental.
Javva is probably previously best known for his incisive but
unpublished analysis of how different toppings affect the aerodynamic
performance of pizza based frisbees.
If you feel this newsletter could be useful to a friend,
why not send them the URL. Note also that Yukio Andoh's
Japanese translation will hopefully be available at
http://www.hatena.org/JavaPerformanceTuning/ in a while.
A note from this newsletter's sponsor
Precise Software revolutionizes J2EE Application Performance
Management with automatic problem detection & correction. Read
our white paper on how to instantly isolate J2EE bottlenecks.
J2EE Performance Master Class
Are your BEA Weblogic/ IBM WebSphere applications running at full throttle?
Register now to attend our Free J2EE Performance Master Class, 18 April in
London.
Please join Jack Shirazi, author of "Java Performance Tuning" from O'Reilly,
and
J2EE experts from Precise Software Solutions to learn how to improve the
performance of your web and J2EE based applications.
To register, click here or call Becky Lunn on 01223 716660.
News
Java performance tuning related news.
Links
Tools
Recent Articles
All the following page references have their tips extracted in the tips section.
Older Pages
All the following page references have their tips extracted in the tips section.
Jack Shirazi
Throughout my career in the IT industry, I?ve been shown many different techniques
to efficiently utilize redundant computing resources. In fact, I?ve even contributed
to the fray by writing a few myself. Every single technique (including mine) were
called load-balancing algorithms. But, was it correct to label them all as load balancing?
And if not, what should they have been called. Well, as it turns out, in many cases,
these techniques (including, gulp, mine) only distributed load. What?s the difference you
ask? From a server's perspective maybe, not a lot. But, from a user's perspective, the
difference can be quite significant. It all comes down to one important metric, response
time. To demonstrate this, lets go back to my experiences with airport security at Charles
du Galle (CDG) in Paris.
CDG's security stations have a very unique queuing system.
If any of you have been through CDG, then you?ll know what I mean.
The queue to each security station is designed in such a way that you cannot tell how
long the queue is, nor can you easily escape once you?ve made your choice of queue.
In general terms, the response time that I experience is a composite of my service time
at the security station and the sum of the service time of everyone else in front of me.
In other airports, once I?ve entered a queue, I can jump to another queue if I feel that
this move will improve my response time. One cannot do this at CDG. In CDG, the physical
layout of the queues reduces the problem to a single queue, single server scenario. Even
though entrances to other security stations at other airports also appear to be a single
queue, single server scenario, it is possible for you to jump queues allowing the system
to achieve a moderate amount of load balancing.
Both of these types of security queues are a far cry from the single
queue multiple server experience that I have at the ticket counter
within airports. And since I?m a frequent flyer, I often get to stand in the priority
queue. In this regard, I'm generally quite happy about the response times I experience.
So, how does this help with the question of what is load balancing and what is load
distribution? It all comes down to this; load balancing is intelligent load distribution.
In other words, I?m going to try to queue up to the the server who is currently under the
least load. Since the queues at CDG offer me no clues as to how long I might have to wait,
it models a simple load distribution system. At other airports, when I can see that the
line to one security station is
short, I can use that information to effect an intelligent balance of the load on the system.
Clearly the system at the ticket counter gives the fairest share as individuals all
wait for the first available
server. And as an added bonus, a priority queue is available to ensure good response
time for those more important tasks. So, the next time you look at a load balancing
system, ask the question: which line should I stand in?
The month we start the round-up with http://javadevtalk.com, a site started
by Chris Wells, Paul Oehler, Anthony Eden, Dustin Williams and Riyad Kalla
(whose photo bears a striking resemblance to Homer Simpson). Each Java
discussion group has taken on it?s own personality and, true to form even with
it?s short existence, so too has javadevtalk. I recommend that you all meet
the new kid on the block.
We start with a thread discussing string comparison. The initial code
int i=0;
while (string1.substring( i, i+1).equals(string2.substring( i, i+1))) {
i+=1;
};
return i;
was condensed to
int i;
for(;string1.charat( i) == string2.charAt( i); i++);
return i;
While one participant responded that one should consider using the new
regex feature in the JDK1.4, this might be a heavy implementation for such
a simple search. One other point, if string1.equals(string2) == true
, both
implementations will throw a StringIndexOutOfBoundsException
which is probably
not desirable.
In an attempt to stir up a good conversation, the moderator posted a topic
with the title
"Avoid SWING when you can". The argument is quite detailed
and the responses are quite thoughtful. As such, it is best that they not
be summarized here.
Treading over to familiar turf, lets see what?s happening at the Salon. In
the category of are we worrying about the right thing, we can find a
question asking about the differences in memory usage between the subclass
and containment relationship between two objects. The answer is: yes of course
there is a difference in the amount of memory used to represent each relationship.
The real problem is that each of subclass and containment notationally express
an important design features. Don't ignore this important distinction
for the sake of saving a few bytes of memory.
The question of using importing * was raised once again. Since * is used as
a notational convention that does not survive compilation, it has no effect
on performance. Having said this, using * can affect readability and hence
understandability of source code. For instance, if you import
com.mycomp.mypackage.*
, others who may have to read the code may not
be able to easily understand which classes are being used.
In another thread, the poster found that his GUI performance was less than
optimal. He was looking for recommendations which tool to use to help fine
tune the application. One response was to compile using the -O option. The
bartender stepped in and pointed out that the -O is ignored. Why is -O ignored?
Here?s an opinion from the Ant developers list. The JDK 1.3 compiler was
completely re-written from scratch. Since Hotspot was included by default in
the JDK 1.3, the authors felt no need to add an extra layer of code for
optimization purposes. This does not say that this will change in the future.
Moving on to www.javagaming.org we find an interesting thread where WORA
seems to break down which results in a performance problem for our gaming friends.
The story starts when a gamer comments that he cannot use the keyboard because
the key press appears to be broken in Linux. Further discussion leads to the
discovery that it may not be a problem with the VM but the behavior is typical
to the way Linux functions. The VM must rely on the OS to provide it with key
events. Of course, this behavior is specific to each platform. In the end, there
is a suggested work around. This does point out the importance of testing your
application on all intended target platforms.
Finally, lets visit www.theserverside.com to see what?s being talked about
there. It was pointed out that there is a .net implementation of the pet store
application at
http://www.gotdotnet.com/team/compare/petshop15whatsnew.asp.
For those familiar with java pet store, this maybe a good introduction into .net.
Next to this was a posting questioning the techno speak "the application/architecture
should be scalable". Fair question, just what does this mean? I?ll combine two
answers to see if we can come up with an answer. A scalable application will maintain
a stable performance profile under load. When load strains the underlying hardware,
a scalable architecture will allow the application to maintain a stable performance
profile as the capacity of the underlying hardware is increased.
The question of entity bean scalability continues to be a hot topic. As EJB
technology matures and developers become more familiar with it, one would hope
that techniques that aid performance would be developed. Again this month there
are more threads regarding EB scaling. The questions of how to scale or will it
scale keeps being asked. The posts that claim that EB do scale never offer any real
clues on how to develop scalable EB systems. Witness this response.
"You need to know what you're doing. If you do not have any
experience and if you don't dare to even open a book on
J2EE, then you'll most likely fail."
Finally
One final note on the subject of load distribution, what follows is a true
story as related to me. "As I approached the security station at Hartsfield
(Atlanta?s airport), I was directed to one of the queues by a blind person.
The person used round robin to direct people to one of the several queues.
He was oblivious to the number of people in the queue. Since the queue he
pointed me to was very long, I ignored him and went to a shorter one." The
point here is not to make jokes about the blind employee. I?m sure he was doing
his utmost to carry out the task assigned to him. More to point is that
people ignored his direction because they had better information than he did.
The real question is, if these people decided against round robin in the real
world, then why is it used so often in the world of computing?
I do owe a note to BEA?s WLS team as just as my last round-up went to press,
they published ECPerf results. Not to be outdone, IBM announced results on
March 13th. The measurements show WebSphere rates at $13/BBops and WebLogic
runs in at $18/BBops. Details can be seen at
http://ecperf.theserverside.com/ecperf.
Kirk Pepperdine.
How did I get here? Ah, one of the great existentialist questions.
In my case, I can answer it. Our Great Leader (OGL) asked me if I'd like to
write a column for his website newsletter. "Something related to Java performance"
he said. "How about if it's related to Java, and I write it real fast?" said I.
Ever noticed how email doesn't let you see someone's reaction?
No bottlenecks, but its slow
OGLs website provides a huge list of tips to make your Java app perform faster.
I could have used these tips years ago to avoid severe embarrassment. I was once
looking for the bottleneck in a bank middleware app. The head of the project
swung by one night when there was just me and another nerd playing with the server.
"How is it going?" he asked. After the usual round of blah blah blah, we got down
to what he really wanted to know: where was the problem?
"Is it I/O?" came the first question. "No" said I, having definitely identified
that the disks were under-utilized and that there was no problem with paging.
"Memory then?" he asked. "No, we've still got lots of spare RAM" I answered.
"Ah, so it's swamping the CPU." he said.
Now, I was working for a middleware app vendor. If it was bottlenecking on the
CPU, it was going to have to be an application problem or else my real boss was
going to be real unhappy. But I hadn't been able to find an application
bottleneck yet. Heck, I hadn't found any bottleneck yet. This was quite a few
years ago, Java was relatively new and the state of profiling tools was quite
basic. And the state of my profiling knowledge was also quite basic. So I
stupidly replied "no, its not the CPU, I haven't found any bottlenecks yet".
In case you haven't thought it through, an application which has no I/O
bottleneck, no memory bottleneck and no CPU bottleneck takes no measurable time
to run. Or at least it's fast enough that it doesn't need someone sitting at a
workstation for days trying to find out why it isn't fast enough. I kept my job,
but I never managed to lose my ability to make stupid statements.
Anyway, I did some hard thinking, and fiddled a bit and finally worked out that
garbage collection (GC) was taking ugly amounts of time. It hadn't shown up in
the method profiling, or at least I hadn't recognized it then if it had. Nowadays,
the first thing I look at is GC. Hopefully, OGLs website will help me avoid
looking stupid in the future sometime, when some obscure new bit of Java isn't
performing and I don't know why.
-Xoptimize
Speaking of obscure Java, I found this tip in OGLs tips page:
"The -Xoptimize flag seems to improve performance on those 1.2.x JVMs that support it."
What the? Where did this -Xoptimize option come from? It sounds like it could
be pretty useful. So I tried to track it down. Info was real sparse. The
originating doc said this:
"Note that the -server option in Java
2 SDK 1.3.0 is equivalent to the -Xoptimize option in Java 2 SDK 1.2.2. The -server
option is recommended for all server-side applications, and is especially useful in
optimizing CPU-intensive code."
But my 1.3 and 1.4 JVMs all recognize the option. Is it just a psedonym for -server?
The Sunsite 1.2 release notes say
"The virtual machine (VM) in version 1.2.2_11 (and prior versions) of the Java 2 SDK,
Standard Edition, recognizes the experimental -Xoptimize command-line option. Future
update versions of the Java 2 SDK 1.2.2 will not have the -Xoptimize option, and the
use of this flag is strongly discouraged. Performance results using this flag have
been very mixed, and there have been failures associated with its use."
And finally, the sun answer book says
"(SPARC only) Experimental only. Spend more time optimizing methods in
the JIT. This option will most likely benefit long-running CPU-bound
applications and might result in increased performance of your application."
Seems like it is the -server option, only not stable in 1.2. Well at least now
I won't look stupid if someone asks me about the -Xoptimize option. [You might
not sound stupid, but I'm not sure about the look - ed.]
Fallacies
I was flicking through some of the Sun guys home pages. Bill Joy's
listed Peter Deutsch's "The Eight Fallacies of Distributed Computing"
which I brought to the attention of OGL. I think he's putting it into
his tips list for this month. So I was thinking, have we got great
fallacies of Java? How about these for starters
- Object creation has no cost.
- Garbage collection can be ignored.
Send me your suggestions. I'll compile them and report back sometime
in the future. Oh, and try to keep them clean. I know some of you
have furtive imaginations.
BCNU
Javva The Hutt.
http://www.onjava.com/pub/a/onjava/2002/03/20/optimization.html
Microtuning (Page last updated March 2002, Added 2002-03-25, Author Jack Shirazi). Tips:
- Performance is dependent on data as well as code. Different data can make identical code perform very differently.
- Always start tuning with a baseline measurement.
- The System.currentTimeMillis() method is the most basic measuring tool for tuning.
- You may need to repeatedly call a method in order to reliably measure its average execution time.
- Minimize the possibility that CPU time will be allocated to anything other than the test while it is running by ensuring no other processes are runing during the test, and that the test remains in the foreground.
- Baseline measurements normally show some useful information, e.g. the average execution time for one call to a method.
- Multiplying the average time taken to execute a method or sequence of methods, by the number of times that sequence will be called in a time period, gives you an estimate of the fraction of the total time that the sequence takes.
- There are three routes to tuning a method: Consider unexpected differences in different test runs; Analyze the algorithm; Profile the method.
- Creating an exception is a costly procedure, because of filling in stack trace.
- A profiler should ideally be able to take a snapshot of performance between to arbitrary points.
- Tuning is an iterative process: you normally find one bottleneck, make changes that improve performance, test those changes, and then start again.
- Algorithm changes usually provide the best speedup, but can be difficult to find.
- Examining the code for the causes of the differences in speed between two variations of test runs can be useful, but is restricted to those tests for which you can devise alternatives that show significant timing variations.
- Profiling is always an option and almost always provides something that can be speeded up. But the law of diminishing returns kicks in after a while, leaving you with bottlenecks that are not worth speeding up, because the potential speedup is too small for the effort required.
- Generic integer parsing (as with the Integer constructors and methods) may be overkill for converting simple integer formats.
- Simple static methods are probably best left to be inlined by the JIT compiler rather than by hand.
- String.equals() is expensive if you are only testing for an empty string. It is quicker to test if the length of the string is 0.
- Set a target speedup to reach. With no target, tuning can carry on for much longer than is needed.
- A generic tuning procedure is: Identify the bottleneck; Set a performance target; Use representative data; Measure the baseline; Analyze the method; Test the change; Repeat.
http://www.javaworld.com/javaworld/jw-03-2002/jw-0315-jms.html
JMS redelivery (Page last updated March 2002, Added 2002-03-25, Author Prakash Malani). Tips:
- Both auto mode (Session.AUTO_ACKNOWLEDGE) and duplicate delivery mode (Session.DUPS_OK_ACKNOWLEDGE) guarantee delivery of messages, but duplicate okay mode can have a higher throughput, at the cost of the occasionally duplicated message.
- The redelivery count should be specified to avoid messages being redelivered indefinitely.
http://www.javaworld.com/javaworld/jw-03-2002/jw-0308-soap.html
Caching SOAP services (Page last updated March 2002, Added 2002-03-25, Author Ozakil Azim and Araf Karsh Hamid). Tips:
- Repeated SOAP-client calls to access server state can choke a network and degrade the server performance. Cache data on the client whenever possible to avoid requests to the server.
- Ensure the client data remains up to date by using a call to a server service which blocks until data is changed.
http://developer.java.sun.com/developer/JDCTechTips/2002/tt0305.html
String concatenation, and IO performance. (Page last updated March 2002, Added 2002-03-25, Author Glen McCluskey). Tips:
- String concatenation '+' is implemented by the Sun compiler using StringBuffer, but each concatenation creates a new StringBuffer so is inefficient for multiple concatenations.
- Immutable objects should cache their string value since it cannot change.
- Operating systems can keep files in their own file cache in memory, and accessing such a memory-cached file is much faster than accessing from disk. Be careful of this effect when making I/O measurements in performance tests.
- Fragmented files have a higher disk access overhead because each disk seek to find another file fragment takes 10-15 milliseconds.
- Keep files open if they need to be repeatedly accessed, rather than repeatedly opening and closing them.
- Use buffering when accessing file contents.
- Explicit buffering (reading data into an array) gives you direct access to the array of data which lets you iterate over the elements more quickly than using a buffered wrapper class.
- Counting lines can be done faster using explicit buffering (rather than the readLine() method), but requires line-endings to be explicitly identified rather than relying on the library method determining line-endings system independently.
http://developer.java.sun.com/developer/community/chat/JavaLive/2002/jl0305.html
Sun community chat on EJBs with Pravin Tulachan (Page last updated March 2002, Added 2002-03-25, Author Edward Ort). Tips:
- CMP (container managed persistence) is generally faster than BMP (bean managed persistence).
- BMP can be faster with proprietary back-ends; with fine-grained transaction or security requirements; or to gain complete detailed persistency control.
- Scalability is improved by passing primary keys rather than passing the entities across the network.
- EJB 2.0 CMP is far faster than EJB 1.1 CMP. EJB 1.1 CMP was not necessarily capable of scaling to high transaction volumes.
- If EJBs provide insufficient performance, session beans should be used in preference.
- Don't make fine-grained method calls across the network. Use value object and session facade design patterns instead.
http://www-106.ibm.com/developerworks/java/library/j-jtctips/j-jtc0219a.html
Double-if on multi-CPU (Page last updated February 2002, Added 2002-03-25, Author Phil Vickers). Tips:
- Double-if logic fails on multiple CPU machines. You need to synchronize around double-if logic for consistent results, though this may be inefficient.
http://www.onjava.com/pub/a/onjava/excerpt/bldgjavaent_8/index3.html
Stateful to Stateless Bean (Page last updated February 2002, Added 2002-03-25, Author Brett McLaughlin). Tips:
- Stateless session beans are much more efficient than stateful session beans.
- Stateless session bean have no state. Most containers have pools of stateless beans. Each stateless bean instance can serve multiplw clients, so the bean pool can be kept small, and doesn't need to change in size avoiding the main pooling overheads.
- A separate stateful bean instance must exist for every client, making bean pools larger and more variable in size.
- [Article discusses how to move a stateful bean implementation to stateless bean implementtaion].
http://www.ddj.com/documents/ddj0204a/
Alternatives to using 'new'. (Page last updated March 2002, Added 2002-03-25, Author Jonathan Amsterdam). Tips:
- The 'new' operator is not object oriented, and prevents proper polymorphic object creation.
- Constructors must be made non-public and preferably private to limit the number of objects of a class.
- The Singleton pattern and the Flyweight (object factory) pattern are useful to limit numbers of objects of various types and to assist with object reuse and reduce garbage collection.
- The real-time specification for Java allows 'new' to allocate objects in a 'current memory region', which may be other than the heap. Each such region is a type of MemoryArea, which can manage allocation.
- Using variables to provide access to limited numbers of objects is efficient, but a maintenance problem if you need to change the object access pattern, for example from a global singleton to a ThreadLocal Singleton.
- A non-static factory method is polymorphic and so provides many advantages over static factory methods.
- The Abstract Factory design pattern uses a single class to create more than one kind of object.
- An alternative to the Flyweight pattern is the Prototype pattern, which allows polymorphic copies of existing objects. The Object.clone() method signature provides support for the Prototype pattern.
- Prototypes are useful when object initialization is expensive, and you anticipate few variations on the initialization parameters. Then you could keep already-initialized objects in a table, and clone an existing object instead of expensively creating a new one from scratch.
- Immutable objects can be returned directly when using Prototyping, avoiding the copying overhead.
http://www.eweek.com/article/0,3658,s=708&a=23125,00.asp
Tuning JVMs for servers. (Page last updated February 2002, Added 2002-03-25, Author Timothy Dyck). Tips:
- Multiple JVMs are often available for a particular platform. Choose the JVM that best suits your needs.
- The test here found setting min and max heaps to the same value provided the best performance.
- Limiting each Sun 1.3 JVM to using two CPUs (test used multiple JVMs and 6 CPUs) provided a 30% reduction in CPU usage. IBM JVMs did not require (or benefit from) this optimization.
http://www.ociweb.com/jnb/jnbMar2002.html
Object Resource Pooling (Page last updated March 2002, Added 2002-03-25, Author Paul King). Tips:
- If the overhead associated with creating a sharable resource is expensive, that resource is a good candidate for pooling.
- Pooled objects create a resource in advance and store it away so it can be reused over-and-over.
- Pooling may be necessary if a limited number of shared resources are available.
- Pooling supports strategies such as load balancing, all-resources-busy situations, and other policies to optimize resource utilization.
- [Article discusses pooling characteristics].
- Load balancing is possible by varying how pooled objects are handed out.
- Pool size can be tuned using low-water and high-water marks.
- Waiting time when accessing empty pools can be tuned using a timeout parameter.
- Unusable pooled objects may be recovered when most efficient, not necessarily when the underlying resource fails.
- The Recycler pattern fixes only the broken parts of a failed object, to minimize the replacement cost.
http://www-106.ibm.com/developerworks/java/library/j-javaio/
Using NIO (Page last updated March 2002, Added 2002-03-25, Author Aruna Kalagnanam and Balu G.). Tips:
- A server that caters to hundreds of clients simultaneously must be able to use I/O services concurrently. Prior to 1.4, an almost one-to-one ratio of threads to clients made servers written in Java susceptible to enormous thread overhead, resulting in both performance problems and lack of scalability.
- The Reactor design pattern demultiplexes events and dispatches them to registered object handlers. (The Observer pattern is similar, but handles only a single source of events where the Reactor pattern handles multiple event sources).
- [Articles covers the changes needed to use java.nio to make a server efficiently muliplex non-blocking I/O from SDK 1.4].
http://www.hpmiddleware.com/newsletters/webservicesnews/features/
J2EE best practices. (Page last updated February 2002, Added 2002-03-25, Author Chris Peltz). Tips:
- Executing a search against the database calls one of the methods. finder() methods must return a collection of remote interfaces, not ValueObjects. Consequently the client would need to make a separate remote call for each remote interface received, to acquire data. The SessionFacade pattern suggests using a session bean to encapsulate the query and return a collection of ValueObjects, thus making the request a single transfer each way.
- The Value Object Assembler pattern uses a Session EJB to aggregate all required data as various types of ValueObjects. This pattern is used to satisfy one or more queries a client might need to execute in order to display multiple data types.
http://www.onjava.com/pub/a/onjava/excerpt/wirelessjava_ch5/index3.html
MIDP GUI programming (Page last updated March 2002, Added 2002-03-25, Author Qusay Mahmoud). Tips:
- Applications with high screen performance needs, like games, need finer control over MIDP screens and should use the javax.microedition.lcdui package which provides the low-level API for handling such cases.
- Always check the drawing area dimensions using Canvas.getHeight() and Canvas.getWidth() [so that you don't draw unnecessarily off screen].
- Not all devices support color. Use Display.isColor() and Display.numColors( ) to determine color support and avoid color mapping [overheads].
- Double buffering is possible by using an offscreen Image the size of the screen. Creating the image:
i = Image.createImage(width, height);
Getting the Graphics context for drawing: i.getGraphics();
Copying to the screen g.drawImage(i, 0, 0, 0);
- Check with Canvas.isDoubleBuffered(), and don't double-buffer if the MIDP implementation already does it for you.
- To avoid deadlock paint() should not synchronize on any object already locked when serviceRepaints() is called.
- Entering alphanumeric data through a handheld device can be tedious. If possible, provide a list of choices from which the user can select.
http://java.sun.com/people/jag/Fallacies.html
The Eight Fallacies of Distributed Computing (Page last updated 2000, Added 2002-03-25, Author Peter Deutsch). Tips:
- The network can fail to deliver at any time.
- Latency is significant.
- Bandwidth is always limited.
http://www.smotricz.com/kabutz/Issue042.html
Inverting booleans (Page last updated February 2002, Added 2002-03-25, Author Heinz M. Kabutz). Tips:
- The fastest way to invert a boolean is to XOR it (bool ^= true).
- Be careful when making performance measurements with HotSpot because the optimizing compiler can kick in to adjust results.
http://www.javaworld.com/javaworld/jw-02-2002/jw-0222-designpatterns.html
The Proxy design pattern. (Page last updated February 2002, Added 2002-03-25, Author David Geary). Tips:
- Creating images is expensive.
- ImageIcon instances create their images when they are constructed.
- If an application creates many large images at once, it could cause a significant performance hit.
- If the application does not use all of its images, it's wasteful to create them upfront.
- Using a proxy, you can delay image loading until the image is required.
- The Proxy pattern often instantiates its real object, the Decorator pattern (which can also use proxy objects) rarely does.
- The java.lang.reflect package provides three classes to support the Proxy and Decorator patterns: Proxy, Method, and InvocationHandler.
http://www-106.ibm.com/developerworks/java/library/j-jtp0305.html
Java Transaction Service (Page last updated March 2002, Added 2002-03-25, Author Brian Goetz). Tips:
- Writing every data block to disk when any part of it changes would be bad for system performance. Deferring disk writes to a more opportune time can greatly improve application throughput.
- Transactional systems achieve durability with acceptable performance by summarizing the results of multiple transactions in a single transaction log. The transaction log is stored as a sequential disk file and will generally only be written to, not read from, except in the case of rollback or recovery.
- Writing an update record to a transaction log requires less total data to be written to disk (only the data that has changed needs to be written) and fewer disk seeks.
- Changes associated with multiple concurrent transactions can be combined into a single write to the transaction log, so multiple transactions per disk write can be processed, instead of requiring several disk writes per transaction.
http://java.sun.com/products/java-media/2D/perf_graphics.html
High performance graphics (Page last updated February 2002, Added 2002-03-25, Author ?). Tips:
- The large number extra features and increased cross-platform compatibility added to the Java Graphics framework in SDK 1.2 made the graphics slower than the 1.1 Graphics. SDK 1.4 targeted these performance issues head on.
- VolatileImage allows you to create hardware-accelerated offscreen images, resulting in better performance of Swing and gaming applications in particular and faster offscreen rendering.
- When filling a shape with a complex paint, Java 2D must query the Paint object every time it needs to assign a color to a pixel whereas a simple color fill only requires iterating through the pixels and assigning the same color to all of them.
- The graphics pipeline (from SDK 1.4) only gets invalidated when an attribute is changed to a different type of value, rather than when an attribute is changed to a different value of the same type. For example rendering one opaque color is the same rendering another opaque color, so this would not invalidate the pipeline. But changing an opaque color to a transparent color would invalidate the pipeline.
- Smaller font is rendered faster than larger font.
- Hardware-accelerated scaling is currently (1.4.0 release) disabled on Win32 because of quality problems, but you can enable it with a runtime flag, -Dsun.java2d.ddscale=true.
- From SDK 1.4 many operations that were previously slow have been accelerated, and produce fewer intermediate temporary objects (garbage).
- Alpha blending and anti aliasing adversely affect performance.
- Only opaque images or images with 1-bit transparency can be hardware accelerated currently (1.4.0).
- Use 1-bit transparency to make the background color of a sprite rectangle transparent so that the character rendered in the sprite appears to move through the landscape of your game, rather than within the sprite box.
- Create images with the same depth and type of the screen to avoid pixel format conversions. Use either Component.createImage() or GraphicsConfiguration.createCompatibleImage(), or use a BufferedImage created with the ColorModel of the screen.
- Rectangular fills--including horizontal and vertical lines--tend to perform better than arbitrary or non-rectangular shapes whether they are rendered in software or with hardware acceleration.
- If your application must repeatedly render non-rectangular shapes, draw the shapes into 1-bit transparency images and copy the images as needed.
- If you experience low frame rates, try commenting out pieces of your code to find the particular operations that are causing problems, and replace these problem operations with something that might perform better.
- Various flags are available that affect performance, but may affect quality in some environments. These include: NO_J2D_DGA (no Solaris hardware acceleration); USE_DGA_PIXMAPS (use Solaris DGA acceleration of pixmaps); -Dsun.java2d.noddraw=true (turn off DirectDraw); -Dsun.java2d.ddoffscreen=false (disable DirectDraw offscreen acceleration); -Dsun.java2d.ddscale=true (enable hardware acceleration in Win32); -Dsun.java2d.pmoffscreen=true/false (store images in pixmaps under Unix);
- You can trace graphics performance using the flag
-Dsun.java2d.trace=<optionname>,<optionname>,...
where the options are log
(print primitives on execution); timestamp
(timestamp log entries); count
(print total calls of each primitive used); out:<filename>
(send logs to filename); verbose
(whatever); help
(help);
http://developer.java.sun.com/developer/J2METechTips/2002/tt0226.html
Minimizing bytecode size for J2ME (Page last updated February 2002, Added 2002-03-25, Author Eric Giguere). Tips:
- Eliminate unnecessary features.
- Avoid inner classes: make the main class implement the required Listener interfaces and handle the callbacks there.
- Use built-in classes if functionality is close enough, and work around their limitations.
- Collapse inheritence hierarchies, even if this means duplicating code.
- Shorten all names (packages, classes, methods, data variables). Some obfuscators can do this automatically. MIDP applications are completely self-contained, so you can use the default package with no possible name-clash.
- Convert array initialization from code to extract data from a binary string or data file. Array initialization generates many bytecodes as each element is separately initialized.
http://dcb.sun.com/practices/devnotebook/gc_perspective.jsp
GC performance tuning (Page last updated February 2002, Added 2002-03-25, Author Alka Gupta and Michael Doyle). Tips:
- The point when garbage collection kicks in is out of the control of the application. This can cause a sequential overhead on the application, as the garbage collector suspends all application threads when it runs, causing inconsistent and unacceptable application pauses, leading to high latency and decreased application efficiency.
- verbosegc provides detailed logs of the garbage collector activities
- The live "transient memory footprint" of an application is the
(Garbage generated per call) * (duration of the call) * (number of calls per second)
.
- GC pause time caused by two-space collection of short-lived objects is directly proportional to the size of the memory space allocated to holding short-lived objects. But smaller available space can mean more frequent GCs.
- Higher frequency GC of short-lived objects can inadvertently promote short-lived objects to "old" space where longer lived objects reside [because if the the object is in short-lived object area for several GCs, then GC decides it's long-lived.] The promoteAll option will force the GC to assume that any object surviving GC of young space is long-lived, and is immediately promoted to old space..
- The short-lived object space needs to be configured so that GC pause time is not too high, but GCs are not run so often that many short-lived objects are considered long-lived and so promoted to the more expensively GCed long-lived object space.
- The long-lived object space needs to be large enough to avoid an out-of-memory error, but not so high that a full GC of old space pauses the JVM for too long.
- [Article covers 1.2 and 1.3 GC memory space models].
- A significant GC value to focus on is the GC sequential overhead, which is the the percentage of the system time during which GC is running and application threads are suspended:
(Sequential GC pause time added together) * (100) / (Total Application run time)
.
- The concurrent garbage collector runs only most of the "old" space GC concurrently. Some of the "old" space GC and all the "young" space GC is sequential.
- GC activity can take hours to settle down to its final pattern. Fragmentation of old space can cause GC times to degrade, and it may take a long time for the old space to become sufficiently fragmented to show this behavior.
- GC options which can reduce fragmentation (such as bestFitFirst).
- The promoteAll option produced a significant improvement in performance [which I find curious].
Jack Shirazi
Last Updated: 2025-03-25
Copyright © 2000-2025 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.
URL: http://www.JavaPerformanceTuning.com/newsletter016.shtml
RSS Feed: http://www.JavaPerformanceTuning.com/newsletters.rss
Trouble with this page? Please contact us