In this article, Rahul Kuchhal demonstrates how to identify and resolve bottlenecks in a J2EE application. This article covers all the steps required for performance tuningbottleneck identification, application server and/or Web server tuning, optimal database configuration, database query optimization, and Java code analysis for best performance. The article also briefly introduces the tools that assist in this process.Read more in How to extract maximum performance from your J2EE Web applications
- Posted by: Dion Almaer
- Posted on: May 17 2004 10:19 EDT
- Article: J2EE application performance optimization by Chris Keene on May 17 2004 16:48 EDT
- J2EE Low Hanging Fruit on Windows Platform by William Louth on May 18 2004 04:08 EDT
- SQL Server by Andre Augusto Oliveira Aragao on May 19 2004 14:30 EDT
- Top J2EE performance problem by Jonathan H on April 14 2011 17:41 EDT
Rahul has written an excellent article on the nitty gritty details of performance tuning J2EE applications, particularly for Windows deployments with the SQL Server database.
The tuning approach outlined in this article aims at moderate gains in existing apps (Rahul suggests a gain of 10% performance improvement is a good target).
For many J2EE apps, the performance-as-afterthought design pattern works fine. For more data-intensive applications (characterized by complex object models and high transaction volumes), good deployment performance requires more in the way of upfront design.
For a discussion of a model-driven approach to J2EE performance, see Avoiding J2EE Bottlenecks: Object-Relational Mapping Insights
Eliminating data bottlenecks in custom enterprise applications
Rahul has written an excellent article on the nitty gritty details of performance tuning J2EE applications, particularly for Windows deployments with the SQL Server database.Yes, the majority of the article deals specifically with the Windows operating system and Microsoft SQL Server RDBMS. So for people like me, who use the Solaris operating system and Oracle RDBMS, that part of Rahul's article is totally irrelevant. Of the tiny part of the article that does not deal with Microsoft products, there isn't much that you won't find in nearly any article on J2EE application performance optimization. Actually, in my opinion, one of Rahul's "tips" for SQL query optimization is misleading:
Consider adding indexes to those columns causing full-table scans for your queriesI get the impression Rahul is saying that full table scans are always bad. This is definitely not the case (as any experienced SQL query optimizer -- for any RDBMS -- will tell you). There are many SQL queries that perform better without an index, and by doing a full table scan.
And if we're plugging each other's "JavaWorld" articles, I hope no-one minds if I plug mine: http://www.javaworld.com/javaworld/jw-10-2003/jw-1003-time.html
There are some useful Windows specific pointers within the article.
Some problems I have with the article are:
- Not another tracing utility that does not practice what the article preaches and is most likely going to execute incorrectly in some environments. The string value returned from thread.getName() is used as an unique key which cannot be assured ignoring the fact that this creates its own micro performance problem in that getName creates a string object from a char array all the time.
- SQL tuning in the article does not take into account that performance metrics can be impacted by other concurrent transactions or SQL executions. It is easy to grab the low hanging fruit in the SQL tier such as adding an index but the poor performance SQL I see in the real world rears its ugly head under heavy transaction concurrency and with some special transactional access mixes. Also why not first approach the problem by not tuning the SQL but getting rid of it altogether.
- SQL profilers cannot see the application transactional behavior which might indicate that the same statement is being executed continously within a resource transaction or across multiple resource transaction with a single user transaction. You get much better performance improvements by addressing the applications transaction execution design. Looking at the access characteristics of particular tables and columns might indicate that a particular domain object (ejb or jdo or pojo) should be considered for caching as it is a reference type object. SQL profilers also cannot help you relate this to the application code (java).
- Current tools do not provide intelligent tuning advice and cannot correlate metrics across different monitoring system or agents. The windows counters provide a big picture to start making some guesses to what could be the problem but merely presenting charts side by side is not going to lead to a solution to a performance problem. I know many tools that claim to correlate such counters but from what I have seen its only time correlation and not connection is made via other contextual information. Users are also forced to correlate via placing bar/point charts side by side.
At the moment I am building a solution to the above problem that will attempt to slay this transaction concurrency dragon for once and for all.
JDBInsight Product Architect
"Tune and Test with Insight"
Looking at the access characteristics of particular tables and columns might indicate that a particular domain object (ejb or jdo or pojo) should be considered for caching as it is a reference type object. SQL profilers also cannot help you relate this to the application code (java).I think this is a major problem in current persistence tools, it is possible to translate dynamic queries and custom QL in log, but it is not trivial to relate generated SQL to the application code (find mapping by table name, find all queries by class name and try to debug and transalate queries).
Do you have ideas how to solve it ?
It must be possible to sove this problem too, but I see no way without modifications in framework.
"it is possible to translate dynamic queries and custom QL in log, but it is not trivial to relate generated SQL to the application code (find mapping by table name, find all queries by class name and try to debug and transalate queries)." - Juozas
JDBInsight 2.1 already provides such a solution for determine what columns and tables are accessed direct or directly by components and classes across tiers (presentation, process and persistence).
The following flash demo shows how it is relatively easy to trace a call across Java architectural layers to the database objects (tables and columns).
You can apply filters to the call trace graph to focus on particular classes or database objects. Timing costs are recording for incoming and outgoing traffice both internal or external to the layer (sometimes referred to as a partition within docs).
This video is a bit old so please check out the latest downloads to see additional improvements.
I believe JDBInsight captures sufficient contextual information to aid performance engineering teams in identifying the root cause of such problems. In 2.1.04 we have extended the profile model by recording in the classloaders, thread, thread groups, code sources (jars or classpath refs), call stack line numbers, as well as J2EE deployment files (ejb-jar.xml, application.xml, web.xml). There is still much more to do but I hope that the adoption of annotations by J2EE spec leads is going to make this easier to implement.
In 2.2 we will also be providing a mechanism to aid developers in the mapping call contexts to properitary persistence frameworks. This will be previewed in a 2.2.x release in June/July.
JDBInsight Product Architect
"Tune and Test with Insight"
I think it is the tool I am looking for.
There´s an important issue we must consider if using Sql Server (it doesn´t matter if J2EE or not): use Stored Procedures.
When you execute a query with Sql Server, it compiles its path every time, even if you use prepared statements, unless you use a Stored Procedure.
I have writtern an article on a similar topic on the most common J2EE application performance problem. Here is the link if you are interested: