Sun Java logo     Previous      Contents      Index      Next     

Sun logo
Sun Java System Application Server Enterprise Edition 8 2004Q4 Beta Performance Tuning Guide 

Chapter 2
Tuning Your Application

This chapter provides information on tuning 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 chapter:


Java Programming Guidelines

This section covers issues related to Java coding and performance. The guidelines outlined are not specific to 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

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 to Concatenate Strings

To improve performance, Instead of using string concatenation, use StringBuffer.append().

String objects are immutable—they never change after creation. Thus, the following code:

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 overusing it can reduce performance significantly.

Assign null to Variables That Are No Longer Needed

Explicitly assigning a null value to variables that are no longer needed 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 leak-free application in steady state will show a steady active heap memory after garbage collections.

Declare Methods as final Only If Necessary

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: for program architecture reasons and maintainability. If you are absolutely certain that a method must not be overridden, use the final keyword.

Declare Constants as static final

The dynamic compiler can perform some constant folding optimizations easily, when the hint is provided.

Avoid Finalizers

Adding finalizers to 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

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.

Synchronize Only When Necessary

Do not 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.

Use DataHandlers for SOAP Attachments

Using a javax.activation.DataHandler for a SOAP attachment to improve performance.

JAX-RPC specifies:

As a result, send an attachment (.gif or XML document) as a SOAP attachment to an RPC style web service by utilizing the Java type mappings. When passing in any of the mandated Java type mappings (appropriate for the attachmented MIME type) as an argument for the web service, the JAX-RPC runtime handles these as SOAP attachments.

For example, to send out an image/gif attachment, use java.awt.Image, or ycreate a DataHandler wrapper over your image. The advantages of using the wrapper are:


JSP and Servlet Tuning

Many applications running on the Application Server use JSPs or servlets in the presentation tier. Servlets and JSPs are entry points to EJBs, which generally implement more complex transactional business logic. This section describes how to improve performance of JSP and servlet applications, both through coding practices and through deployment and configuration settings.

Suggested Coding Practices

This section provides some tips on coding practices that improve JSP and servlet performance.

General Guidelines

Follow these general guidelines to increase performance of JSP and servlet applications:

Avoid shared, modified class variables

In the servlet multithread model (the default), 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, avoid using shared modified class variables, since they create the need for synchronization.

HTTP Session Handling

Follow these guidelines when using HTTP sessions:

Configuration and Deployment Tips

The following configuration tips also improve performance. These tips are intended for production environments, not development.

Disable Security Manager

The security manager is expensive because calls to required resources must call the doPrivileged() method and must also check the resource with the server.policy file. If you are sure that no malicious code will be run on the server and you do not use authentication within your application, then you can disable the security manager.

To disable use of the server.policy file, use the Admin Console. Under Domain > Configurations > config-name > JVM Settings (JVM Options) delete the option that looks like this:

-Djava.security.policy=${com.sun.aas.instanceRoot}/config/server.policy


EJB Performance Tuning

The Application Server's high-performance EJB container has tunable parameters that affect performance. Individual EJBs also have tunable parameters that affect performance. An individual EJB's setting overrides the value of the same setting for the EJB container. The default values are designed for a single-processor computer system. Change the default values to optimize for other system configurations.

The goals of EJB performance tuning are:

General Guidelines

The following guidelines can improve performance of EJB components. Keep in mind that decomposing an application into many EJBs creates overhead and can degrade performance. EJBs are not simply Java objects. They are components with semantics for remote call interfaces, security, and transactions, as well as properties and methods.

Use High Performance Beans

The various types of EJBs are listed below, from the highest performance to the lowest:

  1. Stateless Session Beans and Message Driven Beans
  2. Stateful Session Beans
  3. Container Managed Persistence (CMP) entity beans configured as read-only
  4. Bean Managed Persistence (BMP) entity beans configured as read-only
  5. CMP beans
  6. BMP beans

Using high-performance beans as much as possible improves the overall performance of your application. See Tuning for Specific Types of EJBs for information on how to improve performance for each bean type.

Use Caching

Caching can greatly improve performance when used wisely. For example:

Use the Appropriate Stubs

The stub classes needed by EJB applications are generated dynamically at runtime when an EJB client needs them. This means that it is no longer necessary to generate the stubs or retrieve the client JAR file when deploying an application with remote EJBs. When deploying an application, it is no longer necessary to specify the --retrieve option, which can speed up deployment.

If you have a legacy rich-client application that directly uses the CosNaming service (not a recommended configuration), then you must generate the stubs for your application explicitly using RMIC. See the Troubleshooting Guide for more details.

Remove Unneeded Stateful Session Beans

Removing them avoids passivation of the stateful session beans, and the attendant disk operations.

Cache and Pool Tuning Tips

Here are some further tuning tips:

Related EJB Considerations

This section describes some related considerations when using EJBs.

Remote versus local interfaces

An EJB can have remote and local interfaces. Remote clients which are not located in the same application server instance use the remote interface to access the bean. Calls to the remote interface require marshalling arguments, transportation of the marshalled data over the network, un-marshaling the arguments, and dispatch at the receiving end.

Local clients in the same application server instance can use the local interface of a bean if provided. Using the local interface is more efficient, since it does not require argument marshalling, transportation and un-marshalling. The arguments are passed by reference and thus the local and remote interfaces can share the passed objects. Therefore, the objects must be implemented properly, so that they are shareable.

If a bean is written to be used only by co-located clients then it makes sense to provide only the local interface for the bean and have clients use the local interface. If, on the other hand, the bean is written in a location-independent manner, then both the remote and local interface can be provided so that remote clients use the remote interface and local clients can use the local interface for efficiency.

Pass-By-Value Versus Pass-By-Reference Semantics

Using the remote and local interface appropriately means that beans can be written that clients can access efficiently. But in some instances it might not be possible to use the local interface, for example when:

For these cases, the Application Server provides a pass-by-reference option which can be used to indicate that when making calls to the remote interface of the bean a co-located client can pass arguments by reference. By default, the Application Server uses pass-by-value semantics for calling the remote interface of a bean even if it is co-located. This can be expensive since pass-by-value semantics copies arguments before passing them.

The pass-by-reference option can be specified at the entire application level or on a per bean basis. If if is specified at the application level then pass-by-reference semantics is used when passing arguments to the remote interface of all beans in the application. If this option is specified at a bean level, then calls to the remote interface of the specified bean use the pass-by-reference semantics. See the Developers Guide for more details about the pass-by-reference flag.

If the access paths to the underlying data are known, then configure beans to use pass by reference. It is possible to specify that an EJB will use pass by reference in the sun-ejb-jar.xml deployment descriptor element <pass-by-reference>true</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.

EJB Transactions

This section provides some tips to improve performance when using transactions.

Use container-managed transactions

Container-managed transactions are preferred for consistency, and provide better performance.

Don't encompass user input time

To avoid resources being held unnecessarily for long periods, a transaction should not encompass user input or user think time.

Identify non-transactional methods

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.

Use TX_REQUIRED for long transaction chains

For very large transaction chains, use the transaction attribute TX_REQUIRED. To ensure EJB methods in a call chain, use the same transaction.

Use lowest cost database locking

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.

Use XA-Capable Data Sources Only When Needed

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 separate JDBC resources and use the appropriate resource in the application.

XA Transactions

To improve performance of transactions involving multiple resources, the Application Server uses last agent optimization (LAO), which allows the configuration of one of the resources in a distributed transaction as a one-phase commit (1PC) resource. Since the overhead of multiple-resource transactions is much higher for a JDBC resource than a message queue, LAO substantially improves performance of distributed transactions involving one JDBC resource and one or more message queues. To take advantage of LAO, configure a JDBC resource as a 1PC resource. Nothing special needs to be done to configure JMS resources.

In global transactions involving multiple JDBC resources, LAO will still result improve performance, however, not as much as for one JDBC resource. In this situation, one of the JDBC resources should be configured as 1PC, and all others should be configured as XA.

Use the Least Expensive Transaction Attribute

Set the following transaction attributes in the EJB deployment descriptor file (ejb-jar.xml). Options are listed from best performance to worst. To improve performance, choose the least expensive attribute that will provide the functionality your application needs:

  1. NEVER
  2. TX_NOTSUPPORTED
  3. TX_MANDATORY
  4. TX_SUPPORTS
  5. TX_REQUIRED
  6. TX_REQUIRESNEW

Using Version Consistency

Use version consistency to improve performance while protecting the integrity of data in the database. Since the application server can use multiple copies of an EJB simultaneously, an EJB's state can potentially become corrupted through simultaneous access.

The standard way of preventing corruption is to lock the database row associated with a particular bean. This prevents the bean from being accessed by two simultaneous transactions and thus protects data. However, it also decreases performance, since it effectively serializes all EJB access.

Version Consistency is another approach to protecting EJB data integrity. To use version consistency, you specify a column in the database to use as a version number. The EJB lifecycle then proceeds like this:

Subsequent uses of the bean behave similarly, except that the ejbLoad() method loads its initial data (including the version number) from an internal cache. This saves a trip to the database. When the ejbStore() method is called, the version number is checked to ensure that the correct data was used in the transaction.

Version consistency is advantageous when you have EJBs that are rarely modified, because it allows two transactions to use the same EJB at the same time. Because neither transaction modifies the data, the version number is unchanged at the end of both transactions, and both succeed. But now the transactions can run in parallel. If two transactions occasionally modify the same EJB, one will succeed and one will fail and can be retried using the new values—which can still be faster than serializing all access to the EJB if the retries are infrequent enough (though now your application logic has to be prepared to perform the retry operation).

To use version consistency, the database schema for a particular table must include a column where the version can be stored. You then specify that table in the sun-cmp-mapping.xml deployment descriptor for a particular bean:

<entity-mapping>
   <cmp-field-mapping>
      ...
   </cmp-field-mapping>
   <consistency>
      <check-version-of-accessed-instances>
         <column-name>OrderTable.VC_VERSION_NUMBER</column-name>
      </check-version-of-accessed-instances>
   </consistency>
</entity-mapping>

In addition, you must establish a trigger on the database to automatically update the version column when data in the specified table is modified. The Application Server requires such a trigger to use version consistency. Having such a trigger also ensures that external applications that modify the EJB data will not conflict with EJB transactions in progress.

For example, the following DDL illustrates how to create a trigger for the Order table:

CREATE TRIGGER OrderTrigger
   BEFORE UPDATE ON OrderTable
   FOR EACH ROW
   WHEN (new.VC_VERSION_NUMBER = old.VC_VERSION_NUMBER)
   DECLARE
   BEGIN
      :NEW.VC_VERSION_NUMBER := :OLD.VC_VERSION_NUMBER + 1;
   END;

Using Request Partitioning

Request partitioning enables you to assign a request priority to an EJB. This gives you the flexibility to make certain EJBs execute with higher priorities than others.

An EJB which has a request priority assigned to it will have its requests (services) executed within an assigned threadpool. By assigning a threadpool to its execution, the EJB can execute independently of other pending requests. In short, request partitioning enables you to meet service-level agreements that have differing levels of priority assigned to different services.

Request partitioning applies only to remote EJBs (those that implement a remote interface). Local EJBs are executed in their calling thread (for example, when a servlet calls a local bean, the local bean invocation occurs on the servlet's thread).

To enable request partitioning:

Tuning for Specific Types of EJBs

This section provides tips for tuning various specific types of EJBs:

Entity Beans

Depending on the usage of a particular entity bean, one should tune max-cache-size so that beans that are used less (e.g. an order that is created and never used after the transaction is over) are cached less, and beans that are used frequently (for example, an item in the inventory that gets referenced very often), are cached more in numbers.

Stateful Session Beans

When a stateful bean represents a user, a reasonable max-cache-size of beans is the expected number of concurrent users on the application server process. If this value is too low (in relation to the steady load of users), beans would be frequently passivated and activated, causing a negative impact on the response times, due to CPU intensive serialization and deserialization as well as disk I/O.

Another important variable for tuning is cache-idle-timeout-in-seconds where at periodic intervals of cache-idle-timeout-in-seconds, all the beans in the cache that have not been accessed for more than cache-idle-timeout-in-seconds time, are passivated. Similar to an HTTP session time-out, the bean is removed after it has not been accessed for removal-timeout-in-seconds. Passivated beans are stored on disk in serialized form. A large number of passivated beans could not only mean many files on the disk system, but also slower response time as the session state has to be deserialized before the invocation.

Checkpoint Only When Needed

In High Availability mode, when using stateful session beans, consider checkpointing only those methods that alter the state of the bean significantly. This reduces the number of times the bean state has to be checkpointed into the persistent store.

Stateless Session Beans

Stateless session beans are more readily pooled than entity or the stateful session beans. Valid values for steady-pool-size, pool-resize-quantity and max-pool-size are the best tunables for these type of beans. Set the steady-pool-size to greater than zero if you want to pre-populate the pool. This way, when the container comes up, it creates a pool with steady-pool-size number of beans. By pre-populating the pool it is possible to avoid the object creation time during method invocations.

Setting the steady-pool size to a very large value can cause unwanted memory growth and can result in large GC times. pool-resize-quantity determines the rate of growth as well as the rate of decay of the pool. Setting it to a small value is better as the decay behaves like an exponential decay. Setting a small max-pool-size can cause excessive object destruction (and as a result excessive object creation) as instances are destroyed from the pool if the current pool size exceeds max-pool-size.

Read-only Entity Beans

Read-only entity beans cache data from the database. Application Server supports read-only beans that use both bean-managed persistence (BMP) and container-managed persistence (CMP). Of the two types, CMP read-only beans provide significantly better performance. In the EJB lifecycle, the EJB container calls the ejbLoad() method of a read-only bean once. The container makes multiple copies of the EJB from that data, and since the beans do not update the database, the container never calls the ejbStore() method. This greatly reduces database traffic for these beans.

If there is a bean that never updates the database, use a read-only bean in its place to improve performance. A read-only bean is appropriate if either

For example, use a read-only bean to represent a top-ten bestseller list of books. Although the list might change occasionally in the database (say, from another bean entirely), the change need not be reflected immediately in an application.

The ejbLoad() method of a read-only bean is handled differently for CMP and BMP beans. For CMP beans, the EJB container calls ejbLoad() only once to load the data from the database; subsequent uses of the bean just copy that data. For BMP beans, the EJB container calls ejbLoad() the first time a bean is used in a transaction. Subsequent uses of that bean within the transaction use the same values. The container calls ejbLoad() for a BMP bean that doesn't run within a transaction every time the bean is used. Therefore, read-only BMP beans still make a number of calls to the database.

To create a read-only bean, add the following to the EJB deployment descriptor sun-ejb-jar.xml:

<is-read-only-bean>true</is-read-only-bean>
<refresh-period-in-seconds>600</refresh-period-in-seconds>

Refresh period

An important parameter for tuning read-only beans is the refresh period, represented by the deployment descriptor entity refresh-period-in-seconds. For CMP beans, the first access to a bean loads the bean's state. The first access after the refresh period reloads the data from the database. All subsequent uses of the bean uses the newly refreshed data (until another refresh period elapses). For BMP beans, an ejbLoad() method within an existing transaction uses the cached data unless the refresh period has expired (in which case, the container calls ejbLoad() again).

This parameter enables the EJB to periodically refresh its "snapshot" of the database values it represents. If the refresh period is less than or equal to 0, the bean is never refreshed from the database (the default behavior if no refresh period is given).

Pre-fetching Container Managed Relationship (CMR) Beans

If a container-managed relationship (CMR)exists in your application, specify that loading one bean will load all its related beans. The canonical example of CMR is an order-orderline relationship where you have one Order EJB that has related OrderLine EJBs. In previous releases of the application server, to use all those beans would require multiple database queries: one for the Order bean and one for each of the OrderLine beans in the relationship.

In general, if a bean has n relationships, using all the data of the bean would require n+1 database accesses. Use CMR pre-fetching to retrieve all the data for the bean and all its related beans in one database access.

For example, you have this relationship defined in the ejb-jar.xml file:

<relationships>
   <ejb-relation>
      <description>Order-OrderLine</description>
      <ejb-relation-name>Order-OrderLine</ejb-relation-name>
      <ejb-relationship-role>
         <ejb-relationship-role-name>
            Order-has-N-OrderLines
         </ejb-relationship-role-name>
         <multiplicity>One</multiplicity>
         <relationship-role-source>
            <ejb-name>OrderEJB</ejb-name>
         </relationship-role-source>
         <cmr-field>
            <cmr-field-name>orderLines</cmr-field-name>
            <cmr-field-type>java.util.Collection</cmr-field-type>
         </cmr-field>
      </ejb-relationship-role>
   </ejb-relation>
</relationships>

When a particular Order is loaded, you can load its related OrderLines by adding this to the sun-cmp-mapping.xml file for the application:

<entity-mapping>
   <ejb-name>Order</ejb-name>
   <table-name>...</table-name>
   <cmp-field-mapping>...</cmp-field-mapping>
   <cmr-field-mapping>
      <cmr-field-name>orderLines</cmr-field-name>
      <column-pair>
         <column-name>OrderTable.OrderID</column-name>
         <column-name>OrderLineTable.OrderLine_OrderID</column-name>
      </column-pair>
      <fetched-with>
         <default>
      </fetched-with>
   </cmr-field-mapping>
</entity-mappping>

Now when an Order is retrieved, the CMP engine issues SQL to retrieve all related OrderLines with a WHERE clause of

OrderTable.OrderID = OrderLineTable.OrderLine_OrderID

This is an outer join. These OrderLines are pre-fetched.

This generally improves performance because it reduces the number of database accesses. However, if the business logic often uses Orders without referencing their OrderLines, then this can have a performance penalty, that is, the system has spent the effort to pre-fetch the OrderLines thatis not actually needed.

Avoid pre-fetching for specific finder methods; this can often avoid that penalty. If, for example, an order bean has two finder methods: a findByPrimaryKey method that uses the orderlines, and a findByCustomerId method that returns only order information and hence doesn't use the orderlines. If you've enabled CMR pre-fetching for the orderlines, both finder methods will pre-fetch the orderlines. However, you can prevent pre-fetching for the findByCustomerId method by including this information in the sun-ejb-jar.xml descriptor:

<ejb>
   <ejb-name>OrderBean</ejb-name>
   ...
   <cmp>
      <prefetch-disabled>
         <query-method>
            <method-name>findByCustomerId</method-name>
         </query-method>
      </prefetch-disabled>
   </cmp>
</ejb>

Monitoring EJBs

When monitoring is enabled for the EJB container, you can examine statistics for the individual beans based on the bean pool and cache settings.

The monitoring command below gives the Bean Cache statistics for a stateful session bean. The following is a sample of the monitoring output:

$./asadmin get --user admin --password netscape --host e4800-241-a --port 4848 -m specjcmp.application.SPECjAppServer.ejb-module.supplier_jar.stateful-sessi on-bean.BuyerSes.bean-cache.*

resize-quantity = -1
cache-misses = 0
idle-timeout-in-seconds = 0
num-passivations = 0
cache-hits = 59
num-passivation-errors = 0
total-beans-in-cache = 59
num-expired-sessions-removed = 0
max-beans-in-cache = 4096
num-passivation-success = 0

The monitoring command below gives the bean pool statistics for a Entity bean:

$./asadmin get --user admin --password netscape --host e4800-241-a --port 4848 -m specjcmp.application.SPECjAppServer.ejb-module.supplier_jar.stateful-entit y-bean.ItemEnt.bean-pool.*

idle-timeout-in-seconds = 0
steady-pool-size = 0
total-beans-destroyed = 0
num-threads-waiting = 0
num-beans-in-pool = 54
max-pool-size = 2147483647
pool-resize-quantity = 0
total-beans-created = 255

The monitoring command below gives the bean pool statistics for a stateless bean.

$./asadmin get --user admin --password netscape --host e4800-241-a --port 4848 -m test.application.testEjbMon.ejb-module.slsb.stateless-session-bean.slsb.be an-pool.*

idle-timeout-in-seconds = 200
steady-pool-size = 32
total-beans-destroyed = 12
num-threads-waiting = 0
num-beans-in-pool = 4
max-pool-size = 1024
pool-resize-quantity = 12
total-beans-created = 42

Tuning the bean involves charting the behavior of the cache and pool for the bean in question over a period of time.

If too many passivations are happening and the VM heap remains fairly small, then the max-cache-size can be increased or the cache-idle-timeout-in-seconds can be increased.

If garbage collection is happening too frequently, and the pool size is growing, but the cache hit rate is small, then the pool-idle-timeout-in-seconds can be reduced to destroy the instances.


Note

Specifying the max-pool-size of zero (0) means that the pool is unbounded. The pooled beans remain in memory unless they are removed by specifying a small interval for the pool-idle-timeout-in-seconds. For production systems, specifying the pool as unbounded is NOT recommended.


Monitoring Individual EJBs

To gather method invocation statistics for all methods in a bean, use this command:

asadmin get -m monitorableObject.*

where monitorableObject is a fully-qualified identifier from the hierarchy of monitorable objects, shown below.

serverInstance.application.applicationName

For standalone beans, use this pattern:

serverInstance.application.applicationName

For example, to get statistics for a method in an entity bean, use this command:

asadmin get -m serverInstance.application.appName.ejb-module
      .moduleName.entity-bean.beanName
.bean-method.methodName.*

To find the possible objects (applications, modules, beans, and methods) and object attributes that can be monitored, use the Admin Console or the asadmin list command, as described in the Administration Guide chapter on monitoring the Application Server.

For statistics on stateful session bean passivations, use this command:

asadmin get -m serverInstance.application.appName.ejb-module
      .moduleName.stateful-session-bean.beanName
.bean-cache.*

From the attribute values that are returned, use the following:

num-passivations
num-passivation-errors
num-passivation-success

JDBC and Database Access

Here are some tips to improve the performance of database access.

Use JDBC Directly

When dealing with large amounts of data, such as searching a large database, use JDBC directly rather than using Entity EJBs.

Encapsulate Business Logic in Entity EJBs

Combine business logic with the Entity EJB that holds the data needed for that logic to process.

Close Connections

To ensure that connections are returned to the pool, always close the connections after use.

Minimize the Database Transaction Isolation Level

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.

Set the database transaction isolation level with the Admin Console on the Resources > JDBC > Connection Pools > PoolName page.

JMS

This section provides some tips to improve performance when using JMS.

Use getConnection()

JMS connections are served from a connection pool. This means that calling getConnection() on a Queue connection factory is fast.

Warning: Previous to version 8.1, it was possible to reuse a connection with a servlet or EJB. That is, the servlet could call getConnection() in its init() method and then continually call getSession() for each servlet invocation. If you use JMS within a global transaction, that no longer works: applications can only call getSession() once for each connection. After than, the connection must be closed (which doesn't actually close the connection; it merely returns it to the pool). This is a general feature of portable J2EE 1.4 applications; the Sun Java System Application Server enforces that restriction where previous (J2EE 1.3-based) application servers did not.

Tune the Message-Driven EJB's Pool Size

Tune the Message-Driven EJB's pool size to optimize the concurrent processing of messages.

Cache Bean-specific Resources

Use the setMesssageDrivenContext() or ejbCreate() method to cache bean specific resources, and release those resources from the ejbRemove() method.

Limit Use of JMS Connections

When designing an application that uses JMS connections make sure you use a methodology that sparingly uses connections, by either pooling them or using the same connection for multiple sessions.

The JMS connection uses two threads and the sessions use one thread each. Since these threads are not taken from a pool and the resultant objects aren't pooled, you could run out of memory during periods of heavy usage.

One workaround is to move createTopicConnection into the init of the JSP.

Make sure to specifically close the session, or it stays open, which ties up resources.



Previous      Contents      Index      Next     


Copyright 2004 Sun Microsystems, Inc. All rights reserved.