Difference between revisions of "Tutorial: Profiling Java Programs"
(→Viewing Threads) |
(→Memory) |
||
Line 71: | Line 71: | ||
When you click on the '''Memory''' button, you get a list of the objects or data-structures that occupy the most amount of space in the heap. | When you click on the '''Memory''' button, you get a list of the objects or data-structures that occupy the most amount of space in the heap. | ||
<br /> | <br /> | ||
− | <center>[[Image: | + | <center>[[Image:JavaVisualVM7.jpg|600px]]</center> |
<br /> | <br /> | ||
The image above shows that the '''Node''' objects of the '''RedBlackTree''' class account for 22% of the memory use. Look at the number of objects, though: 602,343 million, taking a total of 24 MBytes! If we were to analyze the program closer we would find that the nodes actually hold ''segments'' that define band of free packing space, or ''rectangles''. If we further look at the packing algorithm, we would notice that whenever a new rectangle is added, it generates only a handful of segments. Since we are packing 20,000 rectangles, the number of segments should be in the 100,000 range, but not 24 million. The reason we have so many is that some of these segments are actually dead, deleted objects, that haven't been caught up by the ''Garbage Collector'' (GC). | The image above shows that the '''Node''' objects of the '''RedBlackTree''' class account for 22% of the memory use. Look at the number of objects, though: 602,343 million, taking a total of 24 MBytes! If we were to analyze the program closer we would find that the nodes actually hold ''segments'' that define band of free packing space, or ''rectangles''. If we further look at the packing algorithm, we would notice that whenever a new rectangle is added, it generates only a handful of segments. Since we are packing 20,000 rectangles, the number of segments should be in the 100,000 range, but not 24 million. The reason we have so many is that some of these segments are actually dead, deleted objects, that haven't been caught up by the ''Garbage Collector'' (GC). |
Revision as of 16:56, 30 September 2013
--D. Thiebaut (talk) 15:01, 30 September 2013 (EDT)
This tutorial is intended to give a brief overview of JVisualVM, the profiler for Java. We use this profiler with Eclipse and use a 2D-packing application as our target application. Our goal is to figure out where the program is spending most of its time. The environment used to create this tutorial is VisualVM 1.3.6 running on OS X 10.7.5, and the hardware is a 2.8 GHz dual quad-core MacPro.
Contents
VisualVM
- On some system Java VisualVM is already part of the installed software, so test first if you have it. It is sometimes in the Applications folder under Java VisualVM, or sometimes it starts in the Terminal with the command jvisualvm.
- VisualVM can be downloaded from visualvm.java.net. Once you have downloaded and installed it, you should be ready for running the application.
- The documentation for VisualVM is available here.
The Packing Application
- The packing application we are going to use for this tutorial is a Processing application. The YouTube movie below illustrates how it proceeds at packing randomly sized rectangles into a larger rectangle.
- Setup the packing application either as an Eclipse project, or using the Processing IDE. If you are using Eclipse, do not forget to include the core.jar as an external library in your Build Path.
- Run the application (or watch the movie) and observe that the application starts quite fast, but slows down significantly. One factor is the fact that the list containing the random rectangles is sorted by decreasing area, and the algorithm picks them largest first, smallest last. So as the algorithm progresses with the packing from left to right, it packs smaller and smaller rectangles and the right frontier advances more slowly than at first.
The second reason is that there is potentially some bottleneck in the program. VisualVM should allow us to look at different aspects of the program.
Starting Monitoring the Processing/Java Application
- First start Java Visual VM.
- Start your packing application. In our case we are starting it from Eclipse. As soon as the applet opens and fills up with purple rectangles, a new entry appears in the Java VisualVM window:
- Click on the new entry, and in the right panel click on Monitor:
- The monitor window presents you with 4 different charts
- CPU (1)
- The CPU chart incates the CPU usage. The documentation is not clear as to what this means on multicore machines. But in the figure above the 30% or so usage seems to indicate the utilization on 1 core. The blue line that overlaps the x-axis is the Garbage Collector, or (GC). If this line is ever growing above the x-axis, it will indicate that your application is creating a lot of objects that it leaves behind, and the GC is busy cleaning up after the application.
- Heap (2)
The Heap graph shows the amount of heap (memory available for dynamic objects) available (in orange) and used up (in blue). If the blue line is very close to the orange one, your application is filling up the heap with objects. You may have a leak in your program.
- Classes (3)
- This is the number of different loaded classes your application uses. You may think that your application is using much fewer classes, but actually all the libraries and imported classes you use in your program contribute to about 2,000 definitions. The number of objects created by your application can easily range in several tens of millions.
- Threads (4)
That's the number of all threads running while your application runs. The packing application has only 3 threads: the main application, the GUI thread, and the packing thread. However, almost 20 live threads are running while the application is on-going.
StackOverflow has interesting answers to the question a programmer asked about "why so many threads!?"
Viewing Threads
- the thread tab shows the diffrrent threads running, waiting, dead. You can easily spot the Main Application Thread and the GUI thread. Our packing thread is harder to spot. But it should be green, as it is running all the time...
Sampling the Application
The Sampler tab offers a lot of very cool information. What the Java Visual VM application does is to regularly sample our Java/Processing application and recording which method or class it is inside of at the sample time, and similarly it looks at the different number of objects currently in the heap.
CPU
When you click the CPU button, you get a list of methods and the amount of time the CPU (or CPUs) are spending in these method, by default sorted from most time consuming to least time consuming.
In the image above we see that our application is spending 31% of the processor time in the get() method of the RedBlackTree class, followed very closely by the getLessThanOrEqual() method of the same class.. Keys() is not far behind with 25% of the time used. So definitely these three methods account for roughly 85% of the time spent by the packing algorithm.
If we were interested in speeding up the application, these would be the three we should look at first.
Memory
When you click on the Memory button, you get a list of the objects or data-structures that occupy the most amount of space in the heap.
The image above shows that the Node objects of the RedBlackTree class account for 22% of the memory use. Look at the number of objects, though: 602,343 million, taking a total of 24 MBytes! If we were to analyze the program closer we would find that the nodes actually hold segments that define band of free packing space, or rectangles. If we further look at the packing algorithm, we would notice that whenever a new rectangle is added, it generates only a handful of segments. Since we are packing 20,000 rectangles, the number of segments should be in the 100,000 range, but not 24 million. The reason we have so many is that some of these segments are actually dead, deleted objects, that haven't been caught up by the Garbage Collector (GC).
This leads us to the concept of memory leak. A memory leak occurs in an application when this application, while running, slowly fills up the heap with objects that are not officially deleted by the program. If an object that is not used by the program is not deleted, then it remains in memory and the GC cannot reclaim its space. It is as if the application is leaking objects in the heap, hence the name we give to this condition. If the number of bytes and number of instances in your application were to increase constantly and significantly in your program to the point of using up all the space, that could be an indication of a memory leak.
References