
Chapter 1 Introduction
Determining factors
Several factors determine how well your application and server configuration
perform.
Response time
Response time is the time required to execute a specified
task, for example, to call an EJB method or submit a JSP form request.
For end users, response time provides the key measurement of performance.
In client-side coding, you can minimize perceived response
time by displaying partial results or status bars. However, in server-side
coding, all you can do is minimize the in-server response time to
an acceptable level. It helps to break down the response time into
time spent in each component and subsystem. Figure 1-1 illustrates the
processing of a Web form request to a JSP that calls an EJB component
which in turn executes a remote database query. A slowdown can occur
in any of these components. When tuning, you must isolate the part
of your deployment that is causing the delay.
Figure 1-0: Response time breakdown
Scalability and throughput
Although a server configuration may perform well with a few
users, response times can increase as the number of connected users
increases. Scalability
is a measure of how
many simultaneous users your application and server configuration
can support under prescribed use patterns before response times increase
to unacceptable levels. Throughput
is a measure
of how many operations the server or application can process in
a given time period; for example, database transactions per second
or Web server page requests per second.
Throughput can be useful in comparing benchmark results for
servers from different vendors, but scalability is a more useful
measurement for tuning a given application deployment. You can directly
measure the number of users and response times. End users are usually
more concerned about how quickly their own work gets done than they
are about overall server performance.
Memory use
Many performance optimizations in EAServer use caching
:
once created, objects such as component instances and database server
connections are pooled for reuse, avoiding the overhead of re-creating
the object. EAServer also caches servlet responses and static HTTP
pages to avoid the overhead of running the servlet or reading files
from disk, respectively. Caching reduces response time at the expense
of increased memory use.
To maximize the performance gain from caching, Sybase recommends
you run EAServer with as much memory as possible, from 1GB minimum
for large deployments up to the limit of the machine architecture
(4GB on most 32-bit address systems).
Common performance problems related to memory use include:
- Memory leaks A memory leak
occurs when code creates
dynamically allocated objects but never releases them. In a Java
or EJB component, you must set object references to null to release
the memory associated with them. When using JDBC connections, you
must release statement objects before releasing connections back
to the connection cache (see "Clean up connections before releasing them to the cache"). Since EAServer pools and reuses
component instances and connection caches, a memory leak can slowly
exhaust the available memory. You can diagnose and find memory leaks
using a profiling tool—see "Profiling
software".
- Swapping Most operating systems support some form of virtual memory,
which allows programs to address more memory than is physically
available on the machine. Excess memory is mapped to data stored
on disk. Swapping
occurs when the system exchanges
in-memory data for data stored on disk. Swapping should be avoided
since the resulting disk I/O slows down the server. Memory
leaks can cause swapping. If you have eliminated memory leaks, you
can avoid swapping by ensuring that the machine has enough memory
to support the EAServer configuration, and by making sure the system's
per-process memory limit allows the server to use all of it. If
you cannot increase physical memory, reduce the server's
memory requirements by adjusting the parameters listed in "EAServer memory requirements".
- Object churning Large, complex objects such as EJB components and database
connections can take considerable time to allocate and construct. Object
churning refers to repeated allocation and deallocation
of the same object. For components, use instance pooling to avoid
this phenomena, as described in "Instance pooling". For database connections, use a
connection cache. You can cache objects of other types within your component,
servlet, or JSP class instance.
Threading
EAServer scales well, primarily through the use of native
platform threads. Threading allows multiple components to execute
concurrently with a minimum of context-switching overhead. Threading
issues that affect performance include:
- Number of threads You can tune the total number of EAServer threads, and partition
the total to different tasks such as IIOP and HTTP request handling.
More threads allow the server to handle more clients. However, if
the number is too high, you may experience thrashing
,
which occurs when each thread gets so little execution time that
more time is spent switching the thread context than running threads.
You can avoid thrashing by reducing the number of threads, adding
CPUs to a multi-CPU machine, or moving to a clustered EAServer deployment.
- Concurrency When different threads share data structures or resources, you
must synchronize their execution so that access to the shared data
or resource is serialized
, that is, accessed
by only one thread at a time. If access to the shared object is
not serialized, you can cause race conditions
, where
overlapping modifications yield unpredictable results, often causing
a crash due to the resulting nonsense data or resource state. However,
excessive serialization can slow down the application by creating
bottlenecks where many threads idle waiting to acquire synchronization
locks. To avoid this problem, do not use design patterns that require
synchronized code. When objects must be shared across threads, minimize
synchronization and design carefully to avoid deadlock. You can
also tune some EAServer settings to minimize internal synchronization
bottlenecks, such as "Flow control".
- Deadlock Deadlock occurs when two or more threads create recursive lock
dependencies and wait indefinitely for each other to release the
locks held. Figure 1-2 illustrates
a deadlock scenario. Component 1 has locked object A while component
2 holds locks on object B. Now component 1 waits for B to be released
while component 2 waits for A to be released.
Figure 1-1: Deadlock example
Deadlock is an extreme problem that can hang the server or
at least the threads that are deadlocked. You can eliminate deadlock
by carefully designing and following a locking protocol that avoids
recursive dependencies when a component locks more than one object
at once. For example, to lock the two objects in Figure 1-2, always lock A
before locking B.
- Thread binding EAServer pools and reuses threads, allowing component instances
to run on any thread rather than being tied to the same thread as
a client connection or the thread that created the instance. Since
most client connections have significant idle time, thread pooling allows
fewer threads to serve more clients. However, if a component uses thread-local
storage, each component instance must be bound to the thread that
created it. Binding the thread significantly reduces scalability,
since the thread cannot be used to run other instances and sits
idle when the component is not running. For more information, see "Thread-related issues".
|
Copyright (C) 2004. Sybase Inc. All rights reserved.
|
|