• Sun
    June 19, 2007

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

Guest Author

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 SizeTransactions/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:

toplink.jdbc.read-connections.min = 2

toplink.jdbc.read-connections.max = 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
    • 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
    build.properties file as appropriate. For example, if the
    admin host is remote, change the value of admin.host from
    the default (localhost) to the appropriate remote host. Also,
    make sure that the javaee.server.passwordfile location is

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

Join the discussion

Comments ( 1 )
  • Karl Friday, February 15, 2008

    Thanks for the info!

Please enter your name.Please provide a valid email address.Please enter a comment.CAPTCHA challenge response provided was incorrect. Please try again.