Performance Tuning Java Code in Tomcat Ethan Henry [email protected] KL Group .
-
Upload
alfred-parsons -
Category
Documents
-
view
225 -
download
1
Transcript of Performance Tuning Java Code in Tomcat Ethan Henry [email protected] KL Group .
Performance Tuning Java Code in Tomcat
Ethan Henry [email protected]
KL Group http://www.klgroup.com
What’s Tomcat• Tomcat is the reference implementation
of the Java Servlet and JavaServer Pages standards developed under the umbrella of the Apache Software Foundation.
• On the chance that you don’t already know, go to: http://jakarta.apache.org
Java Servlets• From a Web perspective, Java Servlets
are a mechanism for extending web servers, similar to CGI, using Java
• From a Java perspective, the Java Servlets specification provides a mechanism for handling & responding to HTTP requests in Java code
• http://java.sun.com/products/servlet
JavaServer Pages• JavaServer Pages are built on top of
servlets and provide a mechanism for creating dynamic web pages using Java and HTML/XML
• http://java.sun.com/products/jsp
Container-Managed Components
• Both Servlets and JSPs (along with EJBs) represent container-managed components (CMCs)
• Unlike regular JavaBeans, these components are being actively managed by an outside entity - the container
• Containers provide functionality and restrict what the component is allowed to do– container decodes HTTP – components have limited multithreaded
behaviour
Performance Elements• There are number of elements in a web
application that can effect performance: – Network Performance– Local Storage Performance– Server (Tomcat) Performance– Java Performance
• Java performance is what we’ll focus on here
Understanding Java Performance
• It is difficult to make simple statements about performance in Java because of the multi-layered nature of most Java programs
Your Servlet
Servlet Container
JVM
OS
Java Bytecode• Java source is compiled to bytecode,
which is then interpreted or compiled into native code by the Java Virtual Machine (JVM)
• There are times when looking at the bytecode can be useful in trying to understand the performance implications of using a particular language construct
javap• javap is a tool that comes with the Java 2
SDK that allows you to disassemble class files and view the bytecode
[D:/work/tune_tomcat] javap -c -classpath . HelloWorld
Compiled from HelloWorld.java
public class HelloWorld extends java.lang.Object {
public HelloWorld();
public static void main(java.lang.String[]);
}
Method HelloWorld()
0 aload_0
1 invokespecial #6 <Method java.lang.Object()>
4 return
Method void main(java.lang.String[])
0 getstatic #7 <Field java.io.PrintStream out>
3 ldc #1 <String "Hello World!">
5 invokevirtual #8 <Method void println(java.lang.String)>
8 return
The Java Virtual Machine
• The JVM is what actually executes the bytecode
• Some old VMs simply interpret the code• Most JDK 1.1 VMs use a Just-In-Time
compiler (JIT)• The HotSpot VM for Java 2• Non-Sun VMs:
– IBM (http://www.ibm.com/java/jdk/download)– Microsoft, HP, Apple– TransVirtual (http://www.transvirtual.com)
Operational Cost Model• There is no common cost model for Java
operations• Without specifying a Java VM &
hardware platform, it’s impossible to know which of these two operations will be more expensive:int a = b + c;Object o = new FooBar();
Operational Cost Model• It’s (almost) always safe to say,
however, that it’s always less expensive to do something less– i.e. the old quicksort (O(log(n)) versus
bubblesort ((O(n2)) comparison
• For this reason, the best suggestion on optimizing Java code is to focus on algorithmic optimizations and not on “cycle-counting”
General Optimization Tips
• The tips are presented roughly in order of the impact they can have on the performance of your program
• Depending on your circumstances, there may be some things you can’t change
• You should try consider changing other things before performing “major surgery” on your code– e.g. buy a faster machine if you can,
determine if I/O bandwidth is the limiting factor, try a different JVM or OS
Major• Tune your VM• Change your VM • Cache• Repartition
Tuning JVM Options• One thing that can have a huge impact
on Java performance is to tune your JVM parameters
• The Sun VM allows you to change:– initial and maximum heap sizejava -Xms<size> -Xmx<size> Foo– the per-thread stack sizejava -Xss<size> Foo
where <size> is a value like 512k or 2m
• These can make a huge different in application performance
Tuning JVM Options• In HotSpot the options are a bit different…
– see http://java.sun.com/products/jdk/1.3/docs/tooldocs/win32/java.html
• You can control:– garbage collection
• -Xincgc enables incremental gc
– memory pool size (different from heap size)• -Xms<size> for initial pool size• -Xmx<size> for max. pool size• -Xss<size> for stack size (the same)
• In general, HotSpot will run Java code faster than a JIT-based VM
Different JVMs• It may not always be possible to switch
VMs, but if it is, it’s worth investigating Sun’s JDK 1.1/1.2 classic Sun’s JDK 1.2 with HotSpot Sun’s JDK 1.3 with Server HotSpot• IBM’s JDK 1.1.8
(http://www.ibm.com/java/jdk/) Apple’s MRJ (http://www.apple.com/java/) Microsoft SDK for Java
(http://www.microsoft.com/java/)
Native Compilers In the context of server-side Java code,
native compilers do not often seem like an obvious choice, but they are a possibility Tower Technology’s TowerJ
(http://www.towerj.com/) NaturalBridge BulletTrain
(http://www.naturalbridge.com/) Instantiations JOVE
(http://www.instantiations.com/)
Evaluating Server-Side VMs
• One popular way of comparing various VMs is the Volano benchmark– http://www.volano.com/benchmarks.html
• But note that you should still test your application, as some VMs are very good with specific types of operations
Caching• Caching is effectively trading memory for
increased performance• The performance of local resources is
almost always better than the performance of remote resources
• The only limit to the effectiveness of caching is the amount of physical memory available– caching to secondary storage is usually not
useful– make sure that the cache isn’t too big, otherwise
it will push other objects out to virtual memory
Caching• Caching can also help reduce network
traffic– having servlets cache database results for use
by multiple user sessions
• Cache things like:– session information
• even if it’s being stored in a database for other reasons like persistence or failover
– database queries– RMI method results
• Finally, check to see where you make redundant calculations
Pooling• Related to caching is pooling, where instead
of data, objects are cached to be reused by the application
• The servlet container may already be doing this - if a servlet implements SingleThreadModel then the container will create multiple instances of the servlet to handle incoming requests
• Pooling is most commonly used with very expensive objects, like database connections– JDBC 2.0 supports ‘connection pooling’
Repartioning• The physical distribution of computing
resources may effect performance• Again local resources are preferred• For example, a servlet that spends most of it’s
time fetching data from a database should be located on the same machine as the database
• If that’s not possible, consider replicating or mirroring the db onto the machine running the servlet and querying it
• If you can’t repartition, reduce network traffic by avoiding fine-grained APIs
Minor• Use StringBuffer• Collection classes• Synchronization• Reduce Object Creation
Use StringBuffer• Using the StringBuffer class instead of
the string concatenation operator (‘+’) is probably the most commonly offered performance tip
• Sometimes it can be a major factor if your program manipulates a lot of strings– i.e. servlets that generate HTML
• In most programs in general, it’s not a major factor
Collections• Use collection classes appropriately• Don’t use Vector• Use a concrete implementation of:
– Map– List– Set
instead• If you need to store large number of double
or int values, use an array instead of a collection and the Integer or Float classes
Collections• In the Sun classic VM, Vectors can be up
to 30x slower than plain arrays and 3x slower than ArrayLists
• In HotSpot it’s much closer, Vectors being only 2x slower
Synchronization• Avoid synchronized methods except
where necessary
Reducing Object Creation
• Creating objects is an expensive operation– more so in pre-HotSpot VMs
• Try to reduce the creation of short-lived, temporary objects
• Use primitives instead of classes like Integer, Double, etc.
• Look for unused objects in your code and remove them
• Use lazy instantiation so objects are only created when needed– reduces startup time
Remove Unused Objectspublic static long methodA(int i) {
IllegalArgumentException ex = new IllegalArgumentException("cannot do negative factorials");
if(i < 0)
throw ex;
else if(i == 0 || i == 1)
return 1;
else
return i*methodA(i-1);
}
public static long methodB(int i) {
if(i < 0)
throw new IllegalArgumentException("cannot do negative factorials");
else if(i == 0 || i == 1)
return 1;
else
return i*methodB(i-1);
}
Remove Unused Objects
• System:
– Thinkpad, Pentium 233 MMX, Windows NT 4.0
– JDK 1.2.2
• For 100,000 iterations:
– classic VM: methodB 170x faster
– HotSpot: methodB 60x faster
– (for calculating 3!)
Memory Usage• Proper memory usage is the key to
stable code for long uptimes• Garbage collection doesn’t solve all
memory management problems• Java programs don’t have memory leaks
like in C++ but are prone to loiterers• Loiterers are objects that are still being
referenced but no longer used
Memory Usage
allocated
reachable
live
Memory leak in Java
Memory leak in C/C++
Measuring Performance• How can use determine whether
changes you’ve made to improve performance have had any effect?
• There are two types of performance measurement:– Load Testing– Profiling
Load Testing• Load testing is a “black box” way of
measuring performance, especially for servlets
• Load testing simulates the load of multiple users accessing the servlet/JSP simultaneously
• Gives a reasonable picture of the user’s actual experience
• Doesn’t show where the problem is occurring
Load Testing • There’s a free tool available (from
Apache) called Apache JMeter that does load testing– http://java.apache.org
• There are plenty of commercial load testing tools:– VeloMeter (http://www.velometer.com)– SilkPerformer (http://www.segue.com)– LoadRunner (http://www.merc-int.com)
Profiling• Profiling is a “white box” way of seeing
what your code is doing• Profiling measures individual methods
or lines of code and tells you how much time is spent in each
• This allows you to quickly find the pieces of code that you need to change
• It doesn’t always correlate with the overall user experience
JVMPI• To allow developer to get detailed profiling
data from the VM, most Java 2 compatible VMs implement the JVM Profiling Interface (JVMPI)– see
http://java.sun.com/products/jdk/1.3/docs/guide/jvmpi
• JVMPI provides calls into a native dll/shared library whenever certain events happen– method enter & exit– object alloc & free– many others
JVMPI• There’s an example of creating your
own JVMPI-based profiling engine at http://www.ddj.com/articles/1999/9909/9909k/
9909k.htm
• If you don’t want to write a lot of JVMPI code, the Sun VM supports creating profiling data in a text file– Use java -classic -Xrunhprof for the
classic VM– Use java -Xprof for the HotSpot VM
JVMPI• for example, here’s some sample output
from JDK 1.2.2 java -Xprof (HotSpot)Flat profile of 0.33 secs (33 total ticks): main
Interpreted + native Method
15.2% 0 + 5 java.util.zip.ZipFile.open
9.1% 0 + 3 java.io.FilePermission$1.run
6.1% 0 + 2 java.io.FileInputStream.readBytes
3.0% 0 + 1 java.lang.StringBuffer.<init>
3.0% 0 + 1 java.lang.ClassLoader.findBootstrapClass
3.0% 0 + 1 java.util.zip.ZipFile.getCSize
3.0% 0 + 1 java.io.Win32FileSystem.getBooleanAttributes
3.0% 0 + 1 java.lang.Class.forName0
3.0% 0 + 1 java.util.zip.Inflater.initIDs
3.0% 1 + 0 java.lang.ClassLoader.loadClass
3.0% 0 + 1 java.io.FileInputStream.close
3.0% 0 + 1 sun.net.www.protocol.file.FileURLConnection.getPermission
3.0% 0 + 1 sun.misc.URLClassPath$2.run
3.0% 1 + 0 java.security.AccessController.doPrivileged
3.0% 0 + 1 sun.misc.URLClassPath$FileLoader.getResource
JVMPI 3.0% 0 + 1 java.io.BufferedReader.readLine
3.0% 0 + 1 java.util.Properties.load
72.7% 2 + 22 Total interpreted
Thread-local ticks:
24.2% 8 Class loader
3.0% 1 Unknown code
Flat profile of 0.00 secs (1 total ticks): Thread-0
Interpreted + native Method
100.0% 0 + 1 java.lang.Thread.<init>
100.0% 0 + 1 Total interpreted
Global summary of 0.73 seconds:
100.0% 74 Received ticks
45.9% 34 Delivered ticks
45.9% 34 All ticks
10.8% 8 Class loader
1.4% 1 Unknown code
References• Larman and Guthrie, Java 2
Performance and idiom Guide, Prentice Hall PTR, 2000
• Haggar, Peter, Practical Java. Addison-Wesley, 2000
• Henry and Lycklama, How Do You Plug Java Memory Leaks? in Dr.Dobb’s Journal, February 2000. Online at:http://www.ddj.com/articles/2000/0002/0002l/
0002l.htm
Questions?