Locating Bottlenecks in Your Code with the Event Profiler

An Oracle JDeveloper How To Document
Written by Shay Shmeltzer, Oracle Corporation
July, 2005

Introduction

Oracle JDeveloper has three built-in profilers that can help you fine-tune your Java application. The profilers monitor Java programs as they run, and collect information about the events and memory consumption during the execution. Using the profilers you can find bottlenecks and memory leaks resulting in improved performance for your application. In this short how-to we focus on the event profiler. This profiler provides information about the events taking place in your application when it runs.

Configuring the Event profiler

To configure the behavior of the event profiler, in JDeveloper 10.1.2 double click your project to go to the project properties and look under the profiler->events node. In JDeveloper 10.1.3 preview these settings are under the tools->preferences menu option.
JDeveloper comes with a set of pre-built events that can be tracked. For each event you can turn tracking on or off, as well as set the color and text to be used in the event profiler window.


Beyond the set of pre-built events, you can define additional events that you want to track. This is useful for tracking the execution of specific code sections in your application.

Profiling with Your own Events

Let's see an example of how using the event profiler we can pin-point a problematic area in our code. We'll use this class to test our performance.
We start with running this method:

   
                                    
                                       
public
                                      
                                    
                                       
static
                                      
                                    
                                       
void
                                      
                                    
main
                                    
(
                                    
String
                                    
[]  
                                    
args
                                    
)  
                                    
                                       
throws
                                      
                                    
SQLException
   
                                    
{
     
                                    
                                       
for
                                      
                                    
(
                                    
                                       
int
                                      
                                    
i  
                                    
=  
                                    
0
                                    
;  
                                    
i  
                                    
<  
                                    
10
                                    
;  
                                    
i
                                    
++
                                    
) 
     
                                    
{
       
                                    
profilerTest  
                                    
myP  
                                    
=  
                                    
                                       
new
                                      
                                    
profilerTest
                                    
()
                                    
;
       
                                    
//TODO add some emp functionality
       
                                    
myP
                                    
.
                                    
printNumEmp
                                    
()
                                    
;
     
                                    
}   
   
                                    
}
                                  

Running it we see the process takes about 2.5 seconds, which is too much time for us.

So we want to check what parts of the code are slow performing. We'll define two profiler events in our code to track the getConnection method and then the execution of the select statement.

Adding an event is quite simple. Firs add the JDeveloper SDK library to your project's libraries. Then in your class's code add import oracle.jdeveloper.profiler.ProfilerAPI;
To mark the start of an event you whish to track add a line like the following:
int my_event_id = ProfilerAPI.startEvent(1234,"my event");
This returns your event code, and when you want to indicate the end of the event that you track add this line:
ProfilerAPI.endEvent(my_event_id);

In our code we add two events:

   
                                    
                                       
private
                                      
                                    
                                       
void
                                      
                                    
printNumEmp
                                    
()  
                                    
                                       
throws
                                      
                                    
SQLException
   
                                    
{
   
                                    
                                       
int
                                      
                                    
connection_event  
                                    
=  
                                    
ProfilerAPI
                                    
.
                                    
startEvent
                                    
(
                                    
CON_EVENT_ID
                                    
,  
                                    
"Connecting to DB"
                                    
)
                                    
;  
                                    
//starting the connection event
     
                                    
Connection  
                                    
myConn  
                                    
=  
                                    
getConnection
                                    
()
                                    
;
   
                                    
ProfilerAPI
                                    
.
                                    
endEvent
                                    
(
                                    
connection_event
                                    
)
                                    
;     
                                    
//ending connection event

   
                                    
                                       
int
                                      
                                    
select_event  
                                    
=  
                                    
ProfilerAPI
                                    
.
                                    
startEvent
                                    
(
                                    
SELECT_EVENT_ID
                                    
,  
                                    
"Selecting data"
                                    
)
                                    
;  
                                    
//starting select event
     
                                    
Statement  
                                    
myStt  
                                    
=  
                                    
myConn
                                    
.
                                    
createStatement
                                    
()
                                    
;
     
                                    
ResultSet  
                                    
results  
                                    
=  
                                    
myStt
                                    
.
                                    
executeQuery
                                    
(
                                    
"select count(*) from emp"
                                    
)
                                    
;
     
                                    
results
                                    
.
                                    
next
                                    
()
                                    
;
     
                                    
System
                                    
.
                                    
out
                                    
.
                                    
println
                                    
(
                                    
results
                                    
.
                                    
getString
                                    
(
                                    
1
                                    
))
                                    
;
   
                                    
ProfilerAPI
                                    
.
                                    
endEvent
                                    
(
                                    
select_event
                                    
)
                                    
;  
                                    
//ending select event

     
                                    
results
                                    
.
                                    
close
                                    
()
                                    
;
     
                                    
myStt
                                    
.
                                    
close
                                    
()
                                    
;
     
                                    
myConn
                                    
.
                                    
close
                                    
()
                                    
;
   
                                    
}
                                  

To make sure we get a clearer picture of the events in the results page we can configure the profiler to display meaning full names.

Event Profiler Configuration

Now when we run the profiler we see more detailed information. A good thing to do here is to order the results by the duration in a descending order - this way we can see that the connection events is taking a lot of time and happens frequently. Maybe we can make our program run faster if we'll try and reuse connections instead of creating them from scratch each time.

Event Profiler Results

The profiler API gives you further control with additional methods that allow you for example to specify a comment to an event (addComment), or add the stack to a comment (addStackToComment). Adding this type of information can help you understand the profiler's results more easily when running longer pieces of code.

Conclusion

Very often the performance of a program can be greatly improved by fixing a small piece of code that gets executed repeatedly. The event profiler in JDeveloper can help you locate the frequency and duration of execution for various parts of your code. Identifying these areas of your code helps you pay special attention to them when tuning to get the most bang-for-the-buck while tuning.

false ,,,,,,,,,,,,,,,