Reputation: 87
I am interested in performance measurements (CPU and disk I/O demands) of Java EE applications.
For CPU I already figured out how to measure the CPU demand of each method invocation. By invoking java.lang.management.ThreadMXBean.getCurrentThreadCpuTime() at the beginning and at the end of each method (e.g. using an EJB interceptor) I can get the ("pure") time which the CPU needed for processing this method (CPU Demand).
Unfortunately, the I/O demand (disk: read and write time for each method invocation) seems to be really hard to measure. The ThreadMXBean does not provide such data. Just substracting the above measured CPU demand from the complete response time of each method is not sufficient due to Suspension and Sync time (also it would be nice to distinguish between read and write if possible).
I was thinking about digging further down to the Operating System interfaces to try to invoke Syscalls or parse other kernel information. Currently I am trying to understand how tools like "sar" measure the "iowait" time and how I could map such data to my Java threads and respective methods. But I am not sure if I am heading in the right direction as my deeper OS knowledge is limited.
Long story short: How can I measure I/O Demand (disk read and write times) for each of my method invocations?
Thanks in advance, bkk
Upvotes: 3
Views: 237
Reputation: 4141
OK, so recently I have developed small utility tool which is measuring some performance metrics for one of our servers. I went with Java Mission Control (jmc) for recording the metrics and parsing the recording file afterward. In my case performance test starting the server and attaching benchmarking tool to it(but you can configure it to attach to already started instance - this link provides more info on how it can be done). I will provide here some essential to your use case lines of code.
1) Before starting the server I was adding to following JMC configurations to the command line:
-XX:+UnlockCommercialFeatures
-XX:+FlightRecorder
-XX:StartFlightRecording=delay=5s,duration=120s,name=recording,filename=recording.jfr
so upon command execution, after 5 second delay it was starting recording with default settings and producing report file after 120 seconds. 2) I was retrieving the I/O statistics using the following method:
FlightRecording flightRecording = FlightRecordingLoader.loadFile(new File(...));
IView recording = flightRecording.createView();
for (IEvent event : recording) {
FLRMethod method = (FLRMethod) event.getValue("((stackTrace).method)");
/* this shows the bytes read by method at some invocation(if any),
so for total bytes read by method you will need to sum manually */
long bytesRead = Long.valueOf(String.valueOf(event.getValue("bytesRead")));
}
You have plenty of things to explore, like the time it taken to read/write file, number of reads, etc.. You would need to experiment a bit to see some of its features. Latest version of Java come bundled with JMC. I have only tried it though with Java 1.7 and 1.8
EDIT: as Klara pointed, you must take into the consideration the thresholds, which can be tuned in your settings file. So the operations which take less than configured threshold they won't be added to the JFR recording.
Upvotes: 1