Sun ONE logo     Previous      Contents      Index      Next     
Sun ONE Application Server 7 Performance Tuning Guide



Tuning Your Application

The following sections provide a comprehensive guide to tuning your applications for maximum performance. A complete guide to writing high performance Java and J2EE applications is beyond the scope of this document.

The following topics are discussed in this module:

Java Programming Guidelines

This section covers issues related to Java coding and performance. The guidelines outlined are not specific to Sun ONE Application Server, but are general rules that are useful in many situations. For a complete discussion of Java coding best practices, refer to the Java BluePrints at http://java.sun.com/blueprints/performance/index.html.

  • Avoid serialization and deserialization, if possible
  • In Java, serialization and deserialization of objects is a CPU-intensive procedure and is likely to slow down your application. Use the transient keyword to reduce the amount of data serialized. Customized readObject() and writeObject() methods may be beneficial, in some cases.

  • Use StringBuffer.append() instead of the "+" operator
  • In Java, Strings are immutable — they never change after creation. For example, the following sequence

    String str = "testing";

    str = str + "abc";

    is understood by the compiler as:

    String str = "testing";

    StringBuffer tmp = new StringBuffer(str);

    tmp.append("abc");

    str = tmp.toString();

    Therefore, copying is inherently expensive and can become a significant factor in hindering performance in case it is overused. Instead, the use of StringBuffer.append() is recommended.

  • Explicitly assign a null value to variables which are no longer needed
  • Doing this helps the garbage collector to easily identify the parts of memory that can be safely reclaimed. While Java automates memory management, it does not prevent usage of excessive amounts of memory or memory leaks. An application may induce memory leaks by holding on to objects without releasing references. This prevents the Java garbage collector from reclaiming those objects, and results in increasing amounts of memory being used. Explicitly nullifying references to unnecessary variables, after each transaction, allows the garbage collector to reclaim memory. One way to detect memory leaks is to employ profiling tools and take memory snapshots after each transaction. A memory leak free application, in steady state, will show a steady active heap memory, after garbage collections.

  • Only when necessary, declare methods as final. Modern optimizing dynamic compilers can perform inlining and other inter-procedural optimizations, even if Java methods are notfinal. Use the keyword as it was originally intended i.e., for program architecture and maintainability reasons. If you are absolutely certain that a method must not be overridden, use the final keyword.
  • Use static final when declaring constants. The dynamic compiler can perform some constant folding optimizations easily, when the hint is provided.
  • Adding finalizers to your code makes the garbage collector more expensive and unpredictable. The virtual machine does not guarantee the time at which finalizers are run. Finalizers may not always be executed, before the program exits. Releasing critical resources in finalize() methods may lead to unpredictable application behavior.
  • Declare method arguments final if they are not modified in the method. In general, declare all variables final if they are not modified after being initialized or set to some value.
  • Don't synchronize code blocks or methods unless synchronization is required. Keep synchronized blocks or methods as short as possible to avoid scalability bottlenecks. Use the Java Collections Framework for unsynchronized data structures instead of more expensive alternatives such asjava.util.HashTable.

J2EE Programming Guidelines

The J2EE model defines a framework for enterprise application development. It defines containers for the basic software components (JSPs, servlets and EJBs) and container services (JAAS, JDBC, JNDI, and JTA for example). While all parts of the J2EE model have their uses, the following sections discuss issues to keep in mind while designing the application architecture.

Servlet and JSP Programming Guidelines

Many applications running on the Sun ONE Application Server are serviced by JSPs or servlets in the presentation tier. Servlets and JSPs are entry points to EJBs, on which more complex transactional business logic is implemented. It is not uncommon to see moderately complex transactional business applications coded entirely using Servlets and other J2EE APIs.

  • In the case of the servlet multithread model which is the default model, a single instance of a servlet is created for each application server instance. All requests for a servlet on that application instance share the same servlet instance. This can lead to thread contention, if there are synchronization blocks in the servlet code. So, the use of shared modified class variables should be avoided as it creates the need for synchronization.
  • Session creation is not for free. If a session is not required do not create one. Invalidate sessions when they are no longer needed.
  • Use the directive <%page session="false"%> to prevent HTTP Sessions from being automatically created when they are not necessary in JSPs.
  • Do not store large objects graphs inside an HttpSession. This forces Java serialization and adds computational overhead.
  • Note that HttpSession access is not transactional. Do not use it as a cache of transactional data, which is typically kept in the database and accessed using Entity beans. Transactions will rollback, upon failures, to their original state. However, stale and inaccurate data may remain in HttpSession objects. Sun ONE Application Server provides "read-only" bean managed persistence entity beans for more cached accesss to read only data.

EJB Programming Guidelines

The following guidelines can improve performance of EJB components in J2EE Applications. For more information, see Sun ONE Application Server Developer's Guide to Enterprise Java Beans Technology.

  • To avoid a JNDI lookup for every request, cache EJB references at the servlet.
  • Cache the EJBHomes in the servlet's init() method. Repeated lookups to an often use home interface and can be expensive.
  • Use the setSessionContext() or ejbCreate() method to cache bean specific resources. This is again an example of using bean lifecycle methods to perform application actions, only once, where possible. Do not forget to place code to release acquired resources in the ejbRemove() method.
  • Reduce the database transaction isolation level when appropriate. Reduced isolation levels reduce work in the database tier, and could lead to better application performance. However, this must be done after carefully analyzing the database table usage patterns. Sun ONE Application Server allows database isolation level to be set under <jdbc-connection-pool> in server configuration file. For more details on server configuration see the Sun ONE Application Server Administrators Guide and the Sun ONE Application Server Administrator's Configuration File Reference.
  • The Sun ONE Application Server ORB provides a mechanism for optimizing calls made from clients which are co-hosted in the same Java Virtual Machine as the server. For example, a servlet code calls an Enterprise Java Bean or one Enterprise Java Bean calling another enterprise bean located on the same server instance. When the servlets and EJB's are running in the same Java virtual machine, run the rmic compiler without the -nolocalstubs flag. This is the default setting i.e -nolocalstubs does not appear in the server configuration file.
  • If the application architecture is such that EJBs are hosted on a remote Application Server, the default behavior must be changed. This can be done via the administration command-line interface asadmin, on the server instance where the application is going to be deployed. The rmic options appear under the JVM Settings tab of the browser based administration interface. Use of local stubs gives significant performance enhancements and is the default behavior of the stub generator.

  • If the application developer is sure about the access paths to the underlying data, then the beans can be configured to use pass by reference. This avoids argument copying on method invocations and result copying on method return. However, problems will arise if the data is modified by another source, during the invocation. This value can be set in the sun-ejb-jar.xml deployment descriptor as follows: <pass-by-reference>true</pass-by-reference>, on a per EJB granularity.
  • Remove Stateful session beans when they are no longer needed. This avoids passivation of the Stateful Session beans, and disk I/O operations.

EJB types are listed below, from the highest performance to the lowest:

    • Stateless Session Beans and Message Driven Beans
    • Stateful Session Beans
    • Entity Beans, with bean managed persistence, configured as read only
    • Entity Beans with Container Managed Persistence (CMP)
    • Entity Beans with Bean Managed Persistence (BMP)

EJB Pool and Cache

Both stateless session beans and entity beans can be pooled to improve server performance. In addition, both stateful session beans and entity beans can be cached to improve performance.

Table:    Bean Type Pooling or Cacheing

Bean Type

Pooled

Cached

Stateless Session

 

Yes

 

No

 

Stateful Session

 

No

 

Yes

 

Entity

 

Yes

 

Yes

 

The difference between a pooled bean and a cached bean is that pooled beans are all equivalent and indistinguishable from one another. Cached beans, on the contrary, contain conversational state in the case of Statefull Session beans, and are associated with a primary key in the case of Entity beans. Entity beans are removed from the pool and added to the cache on ejbActivate() and removed from the cache and added to the pool on ejbPassivate(). ejbActivate() is called by the container when a needed Entity bean is not in the cache. ejbPassivate() is called by the container when the cache grows beyond its configured limits.

Here are some steps you can take when tuning the EJB pool and cache settings:

  • The EJB pool is used by Stateless Session and Entity EJB's. Keeping in mind how you use Stateless Session EJB's and the amount of traffic your server handles, tune the pool size to prevent excessive creation and deletion. Refer to the bean-pool sun-ejb-jar.xml deployment descriptor.
  • The Cache is used by Stateful Session EJB's. Keeping in mind how your applications uses Stateful Session EJB's and the amount of traffic your server handles, tune the EJB cache size and time-out settings to minimize the number of activations and passivations. Refer to the bean-cache element in the sun-ejb-jar.xml deployment descriptor.
  • Allow Stateful Session EJB's to be removed from the container cache by explicitly calling of the remove() method in the client.
  • Entity Beans use both the EJB pool and cache settings. Tune the entity EJB's pool size to minimize the creation and destruction of beans. Prepopulating the pool with a non-zero steady size is useful to get better response for initial requests.
  • Use the setEntityContext() method to cache bean specific resources and release them from the unSetEntityContext() method.
  • Use Lazy Loading to avoid unnecessary preloading of child data.
  • Configure read-only entity beans for read only operations.

Transactions

Here are some steps you can take when using transactions:

  • To avoid resources being held unnecessarily for long periods, a transaction should not encompass user input or user think time.
  • Container managed transactions are preferred for consistency, and provide better performance.
  • Declare non-transactional methods of session EJB's with 'NotSupported' or 'Never' transaction attributes. These attributes can be found in the ejb-jar.xml deployment descriptor file. Transactions should span the minimum time possible since they lock database rows.
  • For very large transaction chains, use the transaction attribute TX_REQUIRED. To ensure EJB methods in a call chain, use the same transaction.
  • Use the lowest cost locking available from the database that is consistent with any transaction. Commit the data after the transaction completes rather than after each method call.
  • When multiple database resources, connector resources and/or JMS resources are involved in one transaction, a distributed or global transaction needs to be performed. This requires XA capable resource managers and data sources. Use XA capable data sources, only when two or more data source are going to be involved in a transaction. If a database participates in some distributed transactions, but mostly in local or single database transactions, it is advisable to register two <jdbc-resource> elements in server configuration file and use the appropriate resource in the application.

JDBC and Database Access

Here are some steps you can take when tuning the JDBC Connection Pool:

  • When dealing with large amounts of data, such as searching a large database, use JDBC directly rather than using Entity EJB's.
  • Combine business logic with the Entity EJB that holds the data needed for that logic to process.
  • To ensure that connections are returned to the pool, always close the connections after use.

JMS

Here are some steps you can take when using JMS:

  • Tune the Message-Driven EJB's pool size to optimize the concurrent processing of messages.
  • Use the setMesssageDrivenContext() or ejbCreate() method to cache bean specific resources, and release those resources from the ejbRemove() method.


  • Note

    Keep in mind that decomposing an application into a moderate to large number of separate EJBs can create an application performance degradation and more overhead. EJBs, unlike JavaBeans, are not simply Java objects. EJBs are higher level entities than Java objects. They are components with remote call interface semantics, security semantics, transaction semantics, and properties.



References


Previous      Contents      Index      Next     
Copyright 2002 Sun Microsystems, Inc. All rights reserved.