Automatically comparing Java profiling results for a single unit test - java

I want to run a single unit test and collect its "profiling" information: how often every method was called, how many instances of certain class were created, how much time did it take to execute certain method/thread, etc. Then, I want to compare this information with some expected values. Are there any Profilers for Java than let me do this (all this should be done automatically, without any GUI or user interaction, of course)?
This is how I want it to work:
public class MyTest {
#Test
public void justTwoCallsToFoo() {
Profiler.start(Foo.class);
Foo foo = new Foo();
foo.someMethodToProfile(); // profiler should collect data here
assertThat(
Profiler.getTotalCallsMadeTo(Foo.class, "barMethod"),
equalTo(3)
);
}
}

Capturing snapshots of profiling information automatically is possible with several Java profilers, you have to add VM parameters to the Java start command to load the profiler and you have to tell the profiler to record data and save a snapshot on exit.
In JProfiler, you could use the "profile" ant task to do this. It takes the profiling settings from a config file that is exported from the JProfiler GUI. You can use the Controller API to start recording and save a snapshot.
Then you have two choices:
You can use the jpcompare command line utility or the corresponding "compare" ant task to compare the snapshot against a known baseline. There are several comparisons available. You can export the results as HTML or in a machine-readable format (CSV/XML).
You can extract data from the snapshot with the jpexport command line utility or the corresponding "export" ant task. Then you can write your own code to analyze the profiling data from a particular run.
For a limited set of profiling data, it is actually possible to use the JProfiler API to write your own profiler that does something like the Profiler.getTotalCallsMadeTo(Foo.class, "barMethod") in your example. See the api/samples/platform example in a JPofiler installation. You would get the information from the hot spot data.
However, for making assertions on whether a specific method was called I would suggest to take an AOP-based approach. Using a profiler-based approach is appropriate for detecting performance regressions.
Disclaimer: My company develops JProfiler.

I found out that this could be done with a J2SE built-in HPROF profiling tool.
java -agentlib:hprof=cpu=times MyTest
It produces a text file formatted like this:
CPU SAMPLES BEGIN (total = 126) Fri Oct 22 12:12:14 2004
rank self accum count trace method
1 53.17% 53.17% 67 300027 java.util.zip.ZipFile.getEntry
2 17.46% 70.63% 22 300135 java.util.zip.ZipFile.getNextEntry
3 5.56% 76.19% 7 300111 java.lang.ClassLoader.defineClass2
4 3.97% 80.16% 5 300140 java.io.UnixFileSystem.list
5 2.38% 82.54% 3 300149 java.lang.Shutdown.halt0
....
Then it's easy to parse the file and extract the methods you're interested in. The solution is completely free and JSE built-in, which is a great benefit comparing to other tools.

Related

How to compare all the variables in two different Eclipse sessions

I am presently trying to find a bug in a long java code. This code reads an input text file and it runs many CFD simulations and then it collects results and analyzes them. In the input file there is a flag that only changes the order in which that bunch of completely independent threads is run. However, if I change this flag I have that the java program crashes after all the simulations are run, while it should actually behave the same. In order to debug this, I opened two different Eclipse sessions, and in each session I run the code. The only difference between the 2 sessions is the value of that flag I mentioned above. I have set up a breakpoint in a line after all the 37 threads (i.e. simulations) are run and results saved on file. That line is in a subroutine where only the main thread is active (all the other threads stopped) and it collects and elaborate further the results of the 37 simulations. I would like to have a way to quickly compare all the variables (in the present scope) of one Eclipse session with the other, in order to find possible differences. Saving them in a text file and comparing the 2 text files would make the trick for me. Do you know how I can do it, if even possible at all? Any other working solutions is also welcomed.

Running clustering algorithms in ELKI

I need to run a k-medoids clustering algorithm by using ELKI programmatically. I have a similarity matrix that I wish to input to the algorithm.
Is there any code snippet available for how to run ELKI algorithms?
I basically need to know how to create Database and Relation objects, create a custom distance function, and read the algorithm output.
Unfortunately the ELKI tutorial (http://elki.dbs.ifi.lmu.de/wiki/Tutorial) focuses on the GUI version and on implementing new algorithms, and trying to write code by looking at the Javadoc is frustrating.
If someone is aware of any easy-to-use library for k-medoids, that's probably a good answer to this question as well.
We do appreciate documentation contributions! (Update: I have turned this post into a new ELKI tutorial entry for now.)
ELKI does advocate to not embed it in other applications Java for a number of reasons. This is why we recommend using the MiniGUI (or the command line it constructs). Adding custom code is best done e.g. as a custom ResultHandler or just by using the ResultWriter and parsing the resulting text files.
If you really want to embed it in your code (there are a number of situations where it is useful, in particular when you need multiple relations, and want to evaluate different index structures against each other), here is the basic setup for getting a Database and Relation:
// Setup parameters:
ListParameterization params = new ListParameterization();
params.addParameter(FileBasedDatabaseConnection.INPUT_ID, filename);
// Add other parameters for the database here!
// Instantiate the database:
Database db = ClassGenericsUtil.parameterizeOrAbort(
StaticArrayDatabase.class,
params);
// Don't forget this, it will load the actual data...
db.initialize();
Relation<DoubleVector> vectors = db.getRelation(TypeUtil.DOUBLE_VECTOR_FIELD);
Relation<LabelList> labels = db.getRelation(TypeUtil.LABELLIST);
If you want to program more general, use NumberVector<?>.
Why we do (currently) not recommend using ELKI as a "library":
The API is still changing a lot. We keep on adding options, and we cannot (yet) provide a stable API. The command line / MiniGUI / Parameterization is much more stable, because of the handling of default values - the parameterization only lists the non-default parameters, so only if these change you'll notice.
In the code example above, note that I also used this pattern. A change to the parsers, database etc. will likely not affect this program!
Memory usage: data mining is quite memory intensive. If you use the MiniGUI or command line, you have a good cleanup when the task is finished. If you invoke it from Java, changes are really high that you keep some reference somewhere, and end up leaking lots of memory. So do not use above pattern without ensuring that the objects are properly cleaned up when you are done!
By running ELKI from the command line, you get two things for free:
no memory leaks. When the task is finished, the process quits and frees all memory.
no need to rerun it twice for the same data. Subsequent analysis does not need to rerun the algorithm.
ELKI is not designed as embeddable library for good reasons. ELKI has tons of options and functionality, and this comes at a price, both in runtime (although it can easily outperform R and Weka, for example!) memory usage and in particular in code complexity.
ELKI was designed for research in data mining algorithms, not for making them easy to include in arbitrary applications. Instead, if you have a particular problem, you should use ELKI to find out which approach works good, then reimplement that approach in an optimized manner for your problem.
Best ways of using ELKI
Here are some tips and tricks:
Use the MiniGUI to build a command line. Note that in the logging window of the "GUI" it shows the corresponding command line parameters - running ELKI from command line is easy to script, and can easily be distributed to multiple computers e.g. via Grid Engine.
#!/bin/bash
for k in $( seq 3 39 ); do
java -jar elki.jar KDDCLIApplication \
-dbc.in whatever \
-algorithm clustering.kmeans.KMedoidsEM \
-kmeans.k $k \
-resulthandler ResultWriter -out.gzip \
-out output/k-$k
done
Use indexes. For many algorithms, index structures can make a huge difference!
(But you need to do some research which indexes can be used for which algorithms!)
Consider using the extension points such as ResultWriter. It may be the easiest for you to hook into this API, then use ResultUtil to select the results that you want to output in your own preferred format or analyze:
List<Clustering<? extends Model>> clusterresults =
ResultUtil.getClusteringResults(result);
To identify objects, use labels and a LabelList relation. The default parser will do this when it sees text along the numerical attributes, i.e. a file such as
1.0 2.0 3.0 ObjectLabel1
will make it easy to identify the object by its label!
UPDATE: See ELKI tutorial created out of this post for updates.
ELKI's documentation is pretty sparse (I don't know why they don't include a simple "hello world" program in the examples)
You could try Java-ML. Its documentation is a bit more user friendly, and it does have K-medoid.
Clustering example with Java-ML |
http://java-ml.sourceforge.net/content/clustering-basics
K-medoid |
http://java-ml.sourceforge.net/api/0.1.7/

Profiling number of garbage-collected object instances per class

I am looking for a tool that can provide VisuaVM-like profiling about live objects, but in non-GUI mode.
The Visual VM functionality I am referring, is accessed by going to the "Profiler" tab and clicking "Memory".
By setting a profile preset of "Profile object allocations and GC" for ever 1 objects (all objects). This gives me exactly what I need in an auto-refreshing view, which I can filter for the class that interests me.
However, I want to be able to export the table of "live objects" to a text file, for every snapshot that is taken (Visual VM refreshes every one seconds). Obviously, pointing and clicking cannot possibly be a solution...
Anyone know of such a "command-line" profiler?
I have been looking at jmap which provides heap dumps, but it is too costly (the dump takes too long, I am just interested in the number of objects).
There is a commercial tool called YourKit but I don't know whether it can do what I need (and also seems rather expensive for the type of "one-off" usage I need it for).
If I could use VisualVM as-is, but have it append the output to a file (instead of refreshing its GUI) it'd be perfect...
I think Class Histograms are what you look for. You could collect the histograms in regular intervals and this will show you number of objects of each class and occupied space. You can then parse the text output yourself in order to:
compare two histograms to see instance allocation/deallocation
filter by a class name
monitor space occupation of class instances over time
Collect class histogram with jmap -histo $pid.

Method for finding memory leak in large Java heap dumps

I have to find a memory leak in a Java application. I have some experience with this but would like advice on a methodology/strategy for this. Any reference and advice is welcome.
About our situation:
Heap dumps are larger than 1 GB
We have heap dumps from 5 occasions.
We don't have any test case to provoke this. It only happens in the (massive) system test environment after at least a weeks usage.
The system is built on a internally developed legacy framework with so many design flaws that they are impossible to count them all.
Nobody understands the framework in depth. It has been transfered to one guy in India who barely keeps up with answering e-mails.
We have done snapshot heap dumps over time and concluded that there is not a single component increasing over time. It is everything that grows slowly.
The above points us in the direction that it is the frameworks homegrown ORM system that increases its usage without limits. (This system maps objects to files?! So not really a ORM)
Question: What is the methodology that helped you succeed with hunting down leaks in a enterprise scale application?
It's almost impossible without some understanding of the underlying code. If you understand the underlying code, then you can better sort the wheat from chaff of the zillion bits of information you are getting in your heap dumps.
Also, you can't know if something is a leak or not without know why the class is there in the first place.
I just spent the past couple of weeks doing exactly this, and I used an iterative process.
First, I found the heap profilers basically useless. They can't analyze the enormous heaps efficiently.
Rather, I relied almost solely on jmap histograms.
I imagine you're familiar with these, but for those not:
jmap -histo:live <pid> > histogram.out
creates a histogram of the live heap. In a nutshell, it tells you the class names, and how many instances of each class are in the heap.
I was dumping out heap regularly, every 5 minutes, 24hrs a day. That may well be too granular for you, but the gist is the same.
I ran several different analyses on this data.
I wrote a script to take two histograms, and dump out the difference between them. So, if java.lang.String was 10 in the first dump, and 15 in the second, my script would spit out "5 java.lang.String", telling me it went up by 5. If it had gone down, the number would be negative.
I would then take several of these differences, strip out all classes that went down from run to run, and take a union of the result. At the end, I'd have a list of classes that continually grew over a specific time span. Obviously, these are prime candidates for leaking classes.
However, some classes have some preserved while others are GC'd. These classes could easily go up and down in overall, yet still leak. So, they could fall out of the "always rising" category of classes.
To find these, I converted the data in to a time series and loaded it in a database, Postgres specifically. Postgres is handy because it offers statistical aggregate functions, so you can do simple linear regression analysis on the data, and find classes that trend up, even if they aren't always on top of the charts. I used the regr_slope function, looking for classes with a positive slope.
I found this process very successful, and really efficient. The histograms files aren't insanely large, and it was easy to download them from the hosts. They weren't super expensive to run on the production system (they do force a large GC, and may block the VM for a bit). I was running this on a system with a 2G Java heap.
Now, all this can do is identify potentially leaking classes.
This is where understanding how the classes are used, and whether they should or should not be their comes in to play.
For example, you may find that you have a lot of Map.Entry classes, or some other system class.
Unless you're simply caching String, the fact is these system classes, while perhaps the "offenders", are not the "problem". If you're caching some application class, THAT class is a better indicator of where your problem lies. If you don't cache com.app.yourbean, then you won't have the associated Map.Entry tied to it.
Once you have some classes, you can start crawling the code base looking for instances and references. Since you have your own ORM layer (for good or ill), you can at least readily look at the source code to it. If you ORM is caching stuff, it's likely caching ORM classes wrapping your application classes.
Finally, another thing you can do, is once you know the classes, you can start up a local instance of the server, with a much smaller heap and smaller dataset, and using one of the profilers against that.
In this case, you can do unit test that affects only 1 (or small number) of the things you think may be leaking. For example, you could start up the server, run a histogram, perform a single action, and run the histogram again. You leaking class should have increased by 1 (or whatever your unit of work is).
A profiler may be able to help you track the owners of that "now leaked" class.
But, in the end, you're going to have to have some understanding of your code base to better understand what's a leak, and what's not, and why an object exists in the heap at all, much less why it may be being retained as a leak in your heap.
Take a look at Eclipse Memory Analyzer. It's a great tool (and self contained, does not require Eclipse itself installed) which 1) can open up very large heaps very fast and 2) has some pretty good automatic detection tools. The latter isn't perfect, but EMA provides a lot of really nice ways to navigate through and query the objects in the dump to find any possible leaks.
I've used it in the past to help hunt down suspicious leaks.
This answer expands upon #Will-Hartung's. I applied to same process to diagnose one of my memory leaks and thought that sharing the details would save other people time.
The idea is to have postgres 'plot' time vs. memory usage of each class, draw a line that summarizes the growth and identify the objects that are growing the fastest:
^
|
s | Legend:
i | * - data point
z | -- - trend
e |
( |
b | *
y | --
t | --
e | * -- *
s | --
) | *-- *
| -- *
| -- *
--------------------------------------->
time
Convert your heap dumps (need multiple) into a format this is convenient for consumption by postgres from the heap dump format:
num #instances #bytes class name
----------------------------------------------
1: 4632416 392305928 [C
2: 6509258 208296256 java.util.HashMap$Node
3: 4615599 110774376 java.lang.String
5: 16856 68812488 [B
6: 278914 67329632 [Ljava.util.HashMap$Node;
7: 1297968 62302464
...
To a csv file with a the datetime of each heap dump:
2016.09.20 17:33:40,[C,4632416,392305928
2016.09.20 17:33:40,java.util.HashMap$Node,6509258,208296256
2016.09.20 17:33:40,java.lang.String,4615599,110774376
2016.09.20 17:33:40,[B,16856,68812488
...
Using this script:
# Example invocation: convert.heap.hist.to.csv.pl -f heap.2016.09.20.17.33.40.txt -dt "2016.09.20 17:33:40" >> heap.csv
my $file;
my $dt;
GetOptions (
"f=s" => \$file,
"dt=s" => \$dt
) or usage("Error in command line arguments");
open my $fh, '<', $file or die $!;
my $last=0;
my $lastRotation=0;
while(not eof($fh)) {
my $line = <$fh>;
$line =~ s/\R//g; #remove newlines
# 1: 4442084 369475664 [C
my ($instances,$size,$class) = ($line =~ /^\s*\d+:\s+(\d+)\s+(\d+)\s+([\$\[\w\.]+)\s*$/) ;
if($instances) {
print "$dt,$class,$instances,$size\n";
}
}
close($fh);
Create a table to put the data in
CREATE TABLE heap_histogram (
histwhen timestamp without time zone NOT NULL,
class character varying NOT NULL,
instances integer NOT NULL,
bytes integer NOT NULL
);
Copy the data into your new table
\COPY heap_histogram FROM 'heap.csv' WITH DELIMITER ',' CSV ;
Run the slop query against size (num of bytes) query:
SELECT class, REGR_SLOPE(bytes,extract(epoch from histwhen)) as slope
FROM public.heap_histogram
GROUP BY class
HAVING REGR_SLOPE(bytes,extract(epoch from histwhen)) > 0
ORDER BY slope DESC
;
Interpret the results:
class | slope
---------------------------+----------------------
java.util.ArrayList | 71.7993806279174
java.util.HashMap | 49.0324576155785
java.lang.String | 31.7770770326123
joe.schmoe.BusinessObject | 23.2036817108056
java.lang.ThreadLocal | 20.9013528767851
The slope is bytes added per second (since the unit of epoch is in seconds). If you use instances instead of size, then that's the number of instances added per second.
My one of the lines of code creating this joe.schmoe.BusinessObject was responsible for the memory leak. It was creating the object, appending it to an array without checking if it already existed. The other objects were also created along with the BusinessObject near the leaking code.
Can you accelerate time? i.e. can you write a dummy test client that forces it to do a weeks worth of calls/requests etc in a few minutes or hours? These are your biggest friend and if you don't have one - write one.
We used Netbeans a while ago to analyse heap dumps. It can be a bit slow but it was effective. Eclipse just crashed and the 32bit Windows tools did as well.
If you have access to a 64bit system or a Linux system with 3GB or more you will find it easier to analyse the heap dumps.
Do you have access to change logs and incident reports? Large scale enterprises will normally have change management and incident management teams and this may be useful in tracking down when problems started happening.
When did it start going wrong? Talk to people and try and get some history. You may get someone saying, "Yeah, it was after they fixed XYZ in patch 6.43 that we got weird stuff happening".
I've had success with IBM Heap Analyzer. It offers several views of the heap, including largest drop-off in object size, most frequently occurring objects, and objects sorted by size.
There are great tools like Eclipse MAT and Heap Hero to analyze heap dumps. However, you need to provide these tools with heap dumps captured in the correct format and correct point in time.
This article gives you multiple options to capture heap dumps. However, in my opinion, first 3 are effective options to use and others are good options to be aware.
1. jmap
2. HeapDumpOnOutOfMemoryError
3. jcmd
4. JVisualVM
5. JMX
6. Programmatic Approach
7. IBM Administrative Console
7 Options to capture Java Heap dumps
If it's happening after a week's usage, and your application is as byzantine as you describe, perhaps you're better off restarting it every week ?
I know it's not fixing the problem, but it may be a time-effective solution. Are there time windows when you can have outages ? Can you load balance and fail over one instance whilst keeping the second up ? Perhaps you can trigger a restart when memory consumption breaches a certain limit (perhaps monitoring via JMX or similar).
I've used jhat, this is a bit harsh, but it depends on the kind of framework you had.

Monitoring Windows directory size

I'm looking for something that will monitor Windows directories for size and file count over time. I'm talking about a handful of servers and a few thousand folders (millions of files).
Requirements:
Notification on X increase in size over Y time
Notification on X increase in file count over Y time
Historical graphing (or at least saving snapshot data over time) of size and file count
All of this on a set of directories and their child directories
I'd prefer a free solution but would also appreciate getting pointed in the right direction. If we were to write our own, how would we go about doing that? Available languages being Ruby, Groovy, Java, Perl, or PowerShell (since I'd be writing it).
There are several solutions out there, including some free ones. Some that I have worked with include:
Nagios
and
Big Brother
A quick google search can probably find more.
You might want to take a look at PolyMon, which is an open source systems monitoring solution. It allows you to write custom monitors in any .NET language, and allows you to create custom PowerShell monitors.
It stores data on a SQL Server back end and provides graphing. For your purpose, you would just need a script that would get the directory size and file count.
Something like:
$size = 0
$count = 0
$path = '\\unc\path\to\directory\to\monitor'
get-childitem -path $path -recurse | Where-Object {$_ -is [System.IO.FileInfo]} | ForEach-Object {$size += $_.length; $count += 1}
In reply to Scott's comment:
Sure. you could wrap it in a while loop
$ESCkey = 27
Write-Host "Press the ESC key to stop sniffing" -foregroundcolor "CYAN"
$Running=$true
While ($Running)
{
if ($host.ui.RawUi.KeyAvailable) {
$key = $host.ui.RawUI.ReadKey("NoEcho,IncludeKeyUp,IncludeKeyDown")
if ($key.VirtualKeyCode -eq $ESCkey) {
$Running=$False
}
#rest of function here
}
I would not do that for a PowerShell monitor, which you can schedule to run periodically, but for a script to run in the background, the above would work. You could even add some database access code to log the results to a database, or log it to a file.. what ever you want.
You can certainly accomplish this with PowerShell and WMI. You would need some sort of DB backend like SQL Express. But I agree that a tool like Polymon is a better approach. The one thing that might make a diffence is the issue of scale. Do you need to monitor 1 folder on 1 server or hundreds?
http://sourceforge.net/projects/dirviewer/ -- DirViewer is a light pure java application for directory tree view and recursive disk usage statistics, using JGoodies-Looks look and feel similar to windows XP.

Categories