Here are some general profiling facts and tips you should be aware of
when profiling your applications:
Profiler calibration - results accuracy:
For each JDK used for profiling the Profiler needs to perform initial
calibration. Obtained data are used for eliminating additional
profiling overhead from collected results in order to deliver accurate
time information. Calibration data are tightly related to system
performance (CPU speed, memory & bus throughput etc.) and JDK
version. Whenever the system performance or JDK may changed, you should
rerun the calibration to ensure that the Profiler collects correct
results.
Runtime optimizations vs. instrumentation:
For getting
methods call tree and timing, Profiler has to
perform instrumentation - this means that original application's
bytecode is slightly modified. If the original code has already been
compiled by JIT compiler to speedup its execution, after
instrumentation it is
switched back to interpreted execution and can run noticeably slower
for some time.
This doesn't necessarily mean that the Profiler imposed such a big
overhead - if set up correctly, it allows the profiled application to
run nearly at its full speed. Ideally, profiled code should be run
several times after instrumentation to allow the VM to apply runtime
optimizations (JIT) again. This ensures that profiling results
representing real application behavior in production environment will
be collected.
Runtime optimizations - skipping simple methods:
Typically, there are many simple methods in an application that don't
take any real time when executing as they are compiled to native code
or inlined. Instrumenting such methods could lead to significant
profiling overhead without any useful results, so profiling
getters/setters and empty methods is disabled by default for Analyze
Performance - Entire Application profiling. This means that you won't
see these methods in call tree or hot spots views. You can change this
behavior by creating Custom Profiling Configuration and explicitely
enabling profiling getters/setters and empty methods.
Runtime optimizations - native routines:
Some arithmetics
functions like Math.sin() are implemented
as Java methods calling native code, but you cannot see them in
collected profiling results. This is because of some execution
optimizations, which cause that these functions are executed directly
in native code, skipping their Java part. In this case the Profiler is
unable to detect that such methods have run and doesn't collect and
display
appropriate calls. You should be aware of this fact when evaluating
profiling results. Concrete functions for 5.0-based JVM are Math.sin(),
Math.cos(), Math.sqrt(). In 6.0-based JVM Math.tan(),
Math.abs(), Math.log() and Math.log10()
functions were added to this list.
Compile time optimizations vs. real profiling
results: When
evaluating profiling results, you should be aware of
Java compiler optimizations, typically string
concatenation or constant expressions evaluation. For example, using System.out.println("Value
of a: " + a) results in creating and dealing with StringBuffer,
eventually
using some parsing/conversion functions to output the value of
float/double variable
'a' as a string. The Profiler is unable to
detect such optimizations and only reports real runtime application's
code flow/behavior.
Dynamic CPU frequency switching: If the
profiled
application runs on a machine with CPU dynamic frequency swiching
capabilities like SpeedStep or PowerNow!, you should ensure that these
are disabled. As the Profiler uses static calibration data describing
system performance to deliver as much exact profiling results as
possible, changing CPU frequency during profiling would significantly
break results accuracy.