How to Get the Best Performance Out of a Java Persistence Implementation

by Rahul Biswas

The Java Persistence API, or simply Java Persistence, introduced in the Enterprise JavaBeans (EJB) 3.0 specification (JSR 220), simplifies the development of Java EE applications that use data persistence. Earlier Tech Tips, such as Converting a POJO to a Persistent Entity, Inheritance and the Java Persistence API, and Using Java Persistence With JavaServer Faces Technology, covered various aspects of the Java Persistence API. This tip discusses how to tune the Java Persistence implementation in GlassFish called Toplink Essentials.

The example included in this tip is based on the customer-cmp sample bundled with GlassFish. You can download the samples from the GlassFish Samples page. The tip covers performance tuning for a Java Persistence implementation used in different modes: in-container and out-of container. The tip also uses the Faban framework to demonstrate different performance tuning parameters.

Before discussing the tuning parameters, let's examine in-container and out-of container modes and the Faban framework.

Two Modes of Running a Java Persistence Implementation

You can use Java Persistence implementations that are compliant with JSR-220 in either of two modes: in-container and out-of-container. This is a marked difference between earlier enterprise Java Persistence implementations such as container-managed persistence in EJB 2.1. With EJB 2.1 container-managed persistence a Java Persistence implementation could only run using in-container mode.

In-container mode means that the Java Persistence implementation is used inside of an EJB container. Entity managers, objects that manage persistence entities, are usually created by the EJB container. Entity managers are typically JTA entity managers. In other words, they participate in transactions controlled by the Java Transaction Architecture (JTA). However, the Java Persistence implementation must support both JTA entity managers and resource-local entity managers, that is, entity managers that participate in transactions not managed by JTA.

In out-of-container mode the Java Persistence implementation is either standalone or runs inside of a web container. The application is responsible for creating it's own entity managers. Transactions are usually resource-local. If the implementation runs standalone, it does not need to support JTA.

The Faban Driver Framework

Faban is an open-source driver framework. It lets developers focus on driver logic implementation so that they can quickly develop performance drivers. Faban takes care of common tasks such as load-generation, output formatting, and the timing of operations. For more about the Faban, see the Faban project page.

Tuning the Sample Application

The customer-cmp sample application interacts with a relational database to store and display information about customer subscriptions to periodicals. The database stores information such as a customer's name and address, as well as the type of periodical to which the customer is subscribed -- that is, magazine, journal, or newspaper. Users can submit requests to the application to display subscription-related information.

This tip focuses on one of the operations supported by the application: finding a customer by his or her ID.

Changing the Cache Size and Number of Connection Pools

Let's examine the impact that specific tuning parameters have on the combined throughput of these operations. Specifically, let's examine the impact of changing the cache size in Toplink Essentials and resetting the number of connections in the connection pool in GlassFish for database calls.

The Toplink Essentials implementation has a default cache size of 1000 per entity. For the purpose of demonstrating the effect of the cache setting, let's look at the transaction rate using the default cache size. Then let's change the cache size to 5000 and compare the results.

To set the cache size, you need to update the persistence.xml file in your project and set the toplink.cache.size.default property as follows:

   <property name="toplink.cache.size.default" value="5000"/>

In this example, there are 20,0000 customer entities in the database.

The cache setting applies to both in-container and out-of-container modes. The connection pool setting, however, is handled differently depending on whether you use in-container or out-of-container mode. For In-container mode, the connection pool setting is done in GlassFish and is controlled by the data-source configuration. In this mode, you can configure the connection pool using the GlassFish admin console as shown below.

Edit Connect Pool

Edit Connect Pool. Click here for a larger image.

For in-container mode, set the number of connections in the connection pool within the container to the number of request processing threads configured in an instance of GlassFish (in this case, 40). This is the maximum number of threads that can be active at any time and thus the maximum number of connections ever needed by Toplink Essentials for database calls.

For out-of-container mode, the connection pool setting is done in the persistence.xml file. The Toplink Essentials implementation has a default connection pool setting of eight connections for both read and write connections. Let's run the application in out-of-container mode for eight users, so set the connection pool value to eight connections.


Running Toplink Essentials using in-container mode produces results similar to the following:

Cache Size Transactions/second
  1000 (default)   1911.493
  5000   3727.253

Running Toplink Essentials using out-of-container mode produces results similar to the following:

Cache Size/
Connection Pool
  1000/default\*   1456.153
  5000/8   6510.0

\* The default values are: = 2 = 2
toplink.jdbc.write-connections.max = 10
toplink.jdbc.write-connections.min = 5

Note that when the default values are used, the connection pool is initialized with the default min setting and can scale to a maximum specified by the default max setting. By setting a connection pool value of 8, there are always be eight connections in the pool.

The system configurations for the tests are as follows:

Sun Fire V880, Solaris 10, 4 CPUs for System under test (SUT).
Sun Fire V880, Solaris 10, 12 CPUs for driver system.

Note that the driver and the SUT are the same system for the out-of-container test. The Driver system and SUT have a point-to-point ethernet connection, which means it has no external network traffic.


To get the best performance out of your Java Persistence implementation, it's important to understand the tuning parameters provided by the implementation.

The cache setting is an important tuning parameter provided by the Toplink Essentials implementation. Tuning the connection pool setting provided by GlassFish is also important in getting the best performance out of any Java Persistence implementation used in GlassFish.

If you use a Java Persistence implementation outside of the EJB container, the cache setting and connection pool setting again play an important role in the performance of the implementation. However, in this case you set the connection pool value in the persistence.xml file.

There are other parameters that might impact the performance of a Java Persistence implementation. One is the statement cache. This needs to set explicitly for some databases such as an Oracle database. The statement cache is turned on by default in the Java DB database bundled with GlassFish.

In addition, your Java Virtual Machine (JVM)\* settings can play an important role in performance tuning. For detailed information on JVM tuning, see the Java Tuning White Paper In running the application for this tip, the JVM options were set to the following values:

  -server -XX:+AggressiveHeap -Xmx2500m -Xms2500m -Xss128k

\* As used in this document, the terms "Java virtual machine" or "JVM" mean a virtual machine for the Java platform.

For More Information

For more information about Java Persistence, see The Java Persistence API - A Simpler Programming Model for Entity Persistence and the Java Persistence API FAQ.

For more information about Toplink Essentials, see TopLink Essentials - The Java Persistence API Implementation at GlassFish.

Running the Sample Code

To install and run the sample code that accompanies this tip:

  1. If you haven't already done so, download GlassFish from the GlassFish Community Downloads Page, and install it.

  2. Set the following environment variables:

    • GLASSFISH_HOME. This should point to where you installed GlassFish.
    • ANT_HOME. This should point to where ant is installed. Ant is included in the GlassFish bundle that you downloaded. (In Windows, it's in the lib\\ant subdirectory.)
    • JAVA_HOME. This should point to the location of JDK 5.0 on your system

    Add $JAVA_HOME/bin, $ANT_HOME/bin, and $GLASSFISH_HOME/bin to your PATH environment variable.

  3. Download the sample package and extract its contents. You should now see the newly extracted directory as <sample_install_dir>/ttmay2007jpaper, where <sample_install_dir> is the directory in which you installed the sample package. The samples directory below ttmay2007jpaper contains the source files and other support files for the sample.

  4. Change to the samples/bp-project directory and edit the file as appropriate. For example, if the admin host is remote, change the value of from the default (localhost) to the appropriate remote host. Also, make sure that the javaee.server.passwordfile location is correct.

  5. Start GlassFish:

      $GLASSFISH_HOME/bin/asadmin start-domain domain1

  6. Change to the samples/javaee5/enterprise/customer-cmp-ear directory and enter the following command:

      ant start-db

  7. Change to the samples/javaee5/enterprise/customer-cmp-ear/setup directory and enter the following commands:

      ant create-db
      ant setup
      ant generate-data
      ant configure-glassfish

  8. To run the benchmark driver in various modes, change to the samples/javaee5/enterprise/customer-cmp-ear/customer-cmp-driver directory and enter the following commands:

    In-container mode, non-optimized:   ant run_inc_default
    In-container mode, optimized:   ant run_inc_optimized
    Out-of-container mode, non-optimized:   ant run_ooc_default
    Out-of-container mode, optimized:   ant run_ooc_optimized

    The output of each run is stored in the samples/javaee5/enterprise/customer-cmp-ear/customer-cmp-driver/output/${runid} directory, where ${runid} is the id of each run displayed on the console during the run. To see the results, view the summary.xml file in that directory.

    After the run is finished, you can undo the tuning settings. Change to the samples/javaee5/enterprise/customer-cmp-ear/setup directory and enter the following command:

      ant unconfigure_glassfish.

About the Author

Rahul Biswas is a member of the Java Performance Engineering group at Sun. He is currently involved in the performance improvement of the persistence implementation in GlassFish.


Thanks for the info!

Posted by Karl on February 15, 2008 at 10:30 AM PST #

Post a Comment:
Comments are closed for this entry.



« August 2016