12 Tips for Better EJB Performance Good EJB design and coding practices result in
thriving high-performance apps Krishna Kothapalli and Raghava Kothapalli
Enterprise JavaBeans (EJBs), the
widely adopted server-side component architecture for the Java 2
Enterprise Edition (J2EE) platform, enable rapid development of
mission-critical applications that are versatile, reusable, and
portable across middleware. At the same time, they protect IT
investment and prevent vendor lock-in. Performance is the key aspect
of any EJB application's success.
To develop high-performance enterprise applications, we should be
aware of the good design and coding practices for performance
improvement. The ideal scenario would be to understand "best
practices" before development begins. In the post-development phase,
the focus shifts to performance tuning of the entire application
including Web server, application server, and database server. The
strategy here is to identify and rectify the weakest link in the
chain. Let's improve that scenario by discussing some general
techniques that help in the design and implementation of a
high-performance EJB-based enterprise application.
EJB Development Our first eight
EJB performance tips are for use during the design and development
stage of your application. The objective here is to identify and fix
problems before they get out of control.
1. Design coarse-grained EJB remote interfaces Because
every method call to an EJB by remote and home interface is a remote
call, the overhead of an intercomponent call will likely be
prohibitive for most fine-grained object interactions. To avoid such
overheads, an EJB should represent an independent business object
that has independent identity and lifecycle. A dependent object
should never be modeled as an EJB. Instead, it should be implemented
as a Java class and included as part of an EJB. For example, a
purchase order may be implemented as an EJB, but individual line
items on a purchase order may be implemented as helper classes, not
as an EJB.
2. Design coarse-grained EJB remote interface methods Each
client call to an EJB is a remote call and involves checks such as
access control, transaction, and activation/passivation. So each
call to an EJB is many times slower than a remote call and magnitude
times slower than a local method call. Reducing the number of calls
improves the performance. One technique in designing coarse-grained
methods is to increase the amount of data passed back and forth in a
method call and combine multiple methods into fewer methods. For
example, Listing 1 shows an
interface that is not a remote preferred interface because the
client needs to make multiple calls to fetch the Person's data. The
code in Listing 2 improves
performance because the number of calls is reduced by using fewer
coarse-grained methods (yet these methods pass more data) in a
method call.
3. Reduce the number of JNDI lookups Depending on the
implementation of the naming and directory service of the
application server, the JNDI lookups may take longer. Some
application servers use separate processes on different machines for
implementing directory information. Caching of the home handles
improves the performance in such situations (see Listing 3). A facade is an
object that provides a single interface to multiple objects. A
server-side facade simplifies the process and makes it so that the
client doesn't have to understand each of the server-side EJBs (see Figure 1). All of the
client calls to the server are routed through the ServerFacade
object. As you can see in Listing 3, ServerFacade is a
session EJB that caches the home handles to all the needed EJBs. The
client could also cache the ServerFacade home handle using a
singleton object on the client side.
4. Use session bean wrapper for returning multiple data rows
from an entity bean Typically each entity bean in your
application represents a logical row in the database. An entity
bean's home interface defines one or more finder methods—one for
each way to find an entity object or collection of entity objects
within the home. A client invokes a finder method on the entity bean
and retrieves a collection of entity objects. The client then loops
through the collection of entity objects and retrieves the data. If
the client is remote, this results in a remote call per row, which
is too costly. Instead of this, a session EJB object (on the server
side) can be used to pack all the rows returned as a result of
calling a finder method on an entity home object. Listing 4 shows a session
object that returns the vector/collection of data rows to the client
in a single call. This approach is useful in cases where data is
static on the GUI—such as in list boxes and spreadsheets. This
approach could be extended to support data modification on the
client side.
5. Use session beans for database batch operations Entity
beans are well suited for database operations involving one logical
row at a time, but they incur a lot of performance overhead for
database batch operations. For example, an entity beans finder
method that returns 1,000 rows performs 1,001 select operations on
the database, which reduces performance drastically. Using session
beans for database batch operations (see Listing 5) improves
performance because it reduces the number of calls to the database.
6. Whenever possible, use container-managed persistence (CMP)
rather than bean-managed persistence (BMP) In BMP, the bean
provider codes database access calls using JDBC, SQLJ, and so on in
bean methods. In CMP, the container provider tools generate database
access calls at the enterprise bean's deployment time. The bean
provider must specify, in the deployment descriptor, the list of
instance fields for which container provider tools must generate
access calls. CMP has the advantage that the bean class can be
independent of the data source. Another advantage is that
application vendors generate optimized code for CMP to improve
database access performance.
7. Use entity beans appropriately Entity beans are
suitable for specific scenarios. They are appropriate to use when
few rows need to be selected from the database and accessed by
multiple clients simultaneously. For example, a person's record
(Person) can be cached during his or her login session and accessed
by multiple EJBs such as SecurityBean, BankAccountBean, and so on.
Therefore, Person can be modeled as an entity bean. Entity beans are
also appropriate to use when rows need to be updated frequently by
multiple transactions.
Because of performance overhead, entity beans are not suitable
when many rows need to be selected, inserted, or updated from the
database such as in batch processing. Consider using a session bean
in such scenarios. Alternatively, you may design coarse-grained
database access operations in an entity bean.
8. Use the right isolation level Isolation level refers to
the degree to which multiple interleaved transactions are prevented
from interfering with each other. TRANSACTION_SERIALIZABLE is the
highest isolation level. This makes the process very slow because
all transactions (even simple reads) must wait in line to execute.
Methods that use this isolation level obtain exclusive write locks
on data, which prevent other transactions from reading, updating, or
inserting data until the transaction is complete. In isolation level
TRANSACTION_REPEATABLE_READ, transactions cannot change data that is
being read by a different transaction. Write locks are used that
prevent other transactions from changing the data. Methods that use
isolation level TRANSACTION_READ_COMMITED cannot read uncommitted
data. A write lock cannot be obtained on data that is already being
changed by another transaction, so reading uncommitted data is not
possible. TRANSACTION_READ_UNCOM- MITED is the lowest transaction
level. Bean methods with this isolation level can read uncommitted
changes, but they are not aware when new records are added.
A higher transaction level is costly in terms of performance. A
lower isolation level typically allows greater concurrency at the
expense of more complicated logic to handle potential data
inconsistencies. A useful guideline is to use the highest isolation
level provided by enterprise information systems that gives
acceptable performance.
Post Design and Development In the
post-development phase of an enterprise application, we need to look
at the issues related to performance tuning of the entire system.
The remaining four tips refer to this phase of the project.
9. Simulate production environment to tune The strategy
here is to look at the entire system, including the Web server,
application server, and database server. You may want to consider
performing these tasks:
- Use entire application
- Use vendor recommended versions and patches
- Simulate production data set
- Use production resources (machines, for example)
- Simulate the user load using stress-testing tools.
10. Use tools to identify performance bottlenecks In this
step, we subject the system to stress and monitor the CPU, memory,
I/O, and network of all the machines. After identifying the
bottleneck area, we drill down and look at the problem in detail. Table 1 lists some of the
testing tools available for different aspects of your program.
11. Tune system parameters Many parameters in your
application are tunable. In your operating system, for example, you
can tune TCP/IP parameters, file limits, process limits, and IPC
limits. In your application server, you can tune connection pool
parameters, EJB pool sizes, thread count, number of JVMs, and JVM
heap size. In your database server, you can tune the number of
connections and processes, shared pool sizes, buffer sizes, indexes,
and SQL query hints. And in your Web server, you can tune connection
keep-alive parameters, thread/process count, and connection
backlog.
12. Use clustering to meet higher loads or consider upgrading
the hardware Sometimes we reach a point where further tuning the
system/code is more expensive than adding new hardware. In such
cases, clustering provides an advantage. Most application servers
provide the clustering feature. An EJB cluster is basically a group
of EJB servers on multiple machines that work together to increase
the horsepower of the system. Typically, each application server in
the cluster contains the same EJBs. Servers in a cluster provide
load balancing using different algorithms such as round robin,
random, sticky bit, server load, and so on. Clustering can be done
at multiple layers as shown in Figure 2.
These 12 tips should help you on your way to designing and
implementing high-performance EJB-based enterprise applications. Use
them to make your apps the best that they can be.
About the Authors Krishna
Kothapalli is an architect in the development of enterprise Java
applications. He has served as a consultant for Xerox Corporation,
Sun Microsystems, Proxicom, General Motors, Sapient Corporation, and
MCI Systemhouse. His areas of interest include object-oriented
distributed systems, Internet, and Java (especially Enterprise
JavaBeans). He has more than eight years of IT experience, four of
which were spent working with Java applications. He has a Masters
degree in computer science from Indian Institute of Technology,
Madras, India. He can be reached at krishna_sunitha@yahoo.com.
Raghava
Kothapalli is a senior developer at EB2X. He has worked with
PeopleSoft, Red Pepper, and Sun Microsystems. He specializes in the
development of extended supply-chain enterprise applications using
Java technologies. He has a PhD degree from Indian Institute of
Technology, Madras, India. He can be reached at raghava@eb2x.com.
|