Posted by Kris GemborysWebSphere Configuration Tips
- Turn on Performance Monitor Interface (PMI) and use standard settings, the standard settings have very small overhead and can be used even in production.
- Use the Performance Monitor Viewer to analyze behavior of various pools
§ DataSource pools
§ Resource Adapter pools
§ Thread pools
§ EJB pools
- Use the Performance Monitor Viewer to analyze
§ Servlet response time
§ EJB response time
- Make sure that “Connection Wait Time” is zero. If “Connection Wait Time” is greater than zero it means that the size of the pool is too small for the given load
- If the size of the pool is too large fetching connection can have measurable impact on the performance when the system is not under stress.
- The minimum size of the heap should be sufficient large to handle the small to medium amount of load without a need for additional memory allocation.
- Setting up Maximum Amount of Heap beyond of 1 GB on 32-but operating system will not have significant impact.
- Do not increase stack size (-Xss) beyond 1 MB on 32-bit OS-es
- Enable Verbose GC and use IBM Support Assistant Workbench to analyze GC logs Verbose GC is possibly the best tool for analyzing memory leaks while load testing J2EE applications and in production.
- Upgrade to the latest JVM Fix Pack; applying WebSphere FixPacks does not apply JVM Fix Packs. In most circumstances the JVM FixPack needs to be downloaded and applied separately.
- Use GC report created using Verbose GC option to adjust heap minimum and maximum sizes as well as heap expanded ratio until an acceptable balance between number of allocation failures and amount of pause time during each garbage collection (-Xms, -Xmx, -Xminf), The large Heap Size increases heap mark and sweep time, and it is a show stopper for all other threads (IBM JVM specific).
- Use GC verbose report to identify the minimum heap size in order to avoid cyclical heap contractions and expansions
- Avoid using System.gc(),GC is a "stop the world" event, meaning that all threads of execution will be suspended except for the GC threads themselves. If you must call GC, do it during a non-critical or idle phase (this is only specific to the IBM JVM implementation, the SUN JVM handles mark and sweep differently)
- Minimize backe-end calls by caching frequently requested data
- Cache frequently used short-lived objects to avoid the need to repeatedly recreate the same objects over and over, and therefore invoke the GC. If you are concerned about memory allocations considering using WekHashMap
- Avoid finalizers
- Use primitive variable types instead of Java object types whenever possible. For example, use int instead of Integer. Using the Java object types still makes more sense in case of data objects because it let you avoid headaches with supporting NULLs.
- Call EJBs by reference instead of by value whenever possible
- Use EJB Local Interfaces (The temote calls, out-of-process, will kill your performance since they are 1000 times slower than in-process calls, this is commonly referred to as round-tripping problem)
- If you use ThreadLocal to store user context
data make sure that you not only remove the data explicitly when you are done but set to null all
referenced object. If you just remove an instance without resetting all
reference objects to null you will end-up with memory leaks and performance
- Avoid storing statefull data to absolute minimum
- Do not use Stateful Session Beans if you plan to support large clusters
- Use JSF managed beans with request scope rather than session scope (the same prnciple as Stateless vs. Stateful Beans)
- When manipulating strings, use StringBuffer or if available StringBuilder
- Avoid excessive writing to Java Standard Output or Standard Error (in one case removing excessive logging in production improved the application performance by 40% without additional code changes)
- Avoid allocating objects within loops, which keeps the object alive on the Java heap longer than necessary.
- If you need to cache referenced data (read only) consider using HashMap, LinkedList, or ArrayList
- If you need to cache data which needs to be updated consider using ConcurrentHashMap or similar Concurrent collections
- Do not use Hashtables
- Limit using synchronization and if you use
synchronization try to use instance synchronization rather than static
synchronization, consider the following simple example to load read-only
reference data. The badFoo() has many problems and in certain scenarios may
even hang. While the goodFoo() is threadsafe even though it does not use
synchronization at all. The trick is in using local varaibles to do all
processing and assigning the final result as atomic operation. The only small
drawback of goodFoo is that the first couple concurrent users will be executing read
and process operations in parraller. This can be resolved by preloading data
when application starts (i.e. ContextListener) rather than using Lazy loading. There are still some other issues with the goodFoo() related to exposing static collection to external manipulation. This can be addressed by returning only cloned elements.