JEP 349: JFR Event Streaming (sandbox preview)

Erik Gahlin erik.gahlin at oracle.com
Fri May 17 16:27:00 UTC 2019


Hi folks,

We have created a sandbox for JEP 349: JFR Event Streaming[1] for people who
like to try the feature out. It is work in progress, but plan is to 
integrate it
in the next couple of months, but not for JDK 13.

A build can be created like this:

  $ hg clone -b JEP-349-branch -r 53dccc90a5be 
http://hg.openjdk.java.net/jdk/sandbox jep-349
  $ cd jep-349
  $ bash configure
  $ make images
  $ ./build/*/images/jdk/bin/java -version

See [2] and [3] for more information on how to use the sandbox 
repository and
build the JDK.

For testing purposes, and to illustrate how the Event Streaming API can be
used, there exists a Java agent[4] that aggregates event data and print the
results on standard out.

Example,
http://cr.openjdk.java.net/~egahlin/health-report-agent/health-report-example.txt
=================== HEALTH REPORT === 2019-05-16 23:57:50 
====================
| GC: G1Old/G1New         Phys. memory: 28669 MB    Alloc Rate: 8 
MB/s       |
| OC Count    : 28        Initial Heap: 448 MB      Total Alloc: 190 
MB      |
| OC Pause Avg: 40.1 ms   Used Heap   : 19 MB       Thread Count: 
20.0       |
| OC Pause Max: 48.8 ms   Commit. Heap: 47 MB       Class Count : 
3894.0     |
| YC Count    : 8         CPU Machine   :  20.12 % Safepoints: 
335          |
| YC Pause Avg: 5.7 ms    CPU JVM User  :  10.28 %  Max Safepoint: 46.4 
ms   |
| YC Pause Max: 22.4 ms   CPU JVM System:   1.07 %  Max Comp. Time: 
728.3 ms |
|--- Top Allocation Methods ------------------------------- 
-----------------|
| DataBufferInt.<init>(int) 11.27 % |
| Component.size() 9.01 % |
| BufferedContext.validate(...) 6.21 % |
| Path2D$Double.<init>(...) 5.87 % |
| SunGraphics2D.clone() 5.85 % |
|--- Hot Methods 
------------------------------------------------------------|
| DRenderer._endRendering(int, int)                                  
51.11 % |
| DRenderer.copyAARow(...) 6.67 % |
| Arrays.fill(...) 4.44 % |
| StringConcatFactory.doStringConcat(...) 2.22 % |
| MarlinTileGenerator.getAlphaNoRLE(...) 2.22 % |
==============================================================================

The agent can be started like this:

  $ java -javaagent:health-report.jar MyApp

The interval at which events are flushed can be changed with the interval
option. The default interval is 1 second. For example, to flush
every ten second, use -javaagent:health-report.jar=interval=10

For quick experimentation, the agent can also be run as a Java program that
allocate objects in a loop.

  $ java Main.java

Two new classes, EventStream[5] and RecordingStream[6], have been added 
to the
jdk.jfr.consumer package. A EventFilter class may be added later for more
advanced filtering.

The JVM implementation is close to finished, but there is work on the 
consumer
side left. There is also an effort to reduce allocation on the client.

To get started without using the agent, the CPU load can be printed
like this:

   Configuration c = Configuration.getConfiguration("default");
   try (RecordingStream r = new RecordingStream(c)) {
     r.onEvent("jdk.CPULoad",  event -> {
       float percentage = 100 * event.getFloat("machineTotal");
       System.out.printf("CPU: %.2f %% \n\n", percentage);
     });
     r.start();
   }

Feedback is very much welcomed!

Thanks
Erik and Markus

Outages, known issues and limitations
-------------------------------------

- Only start/open one RecordingStream at a time
Implementation has not been tested with two RecordingStreams 
simultaneously.

- Exception handling
Behavior is undefined if an exception is thrown in a handler.

- Parser level filtering disabled
Purpose of parser level filtering is to be able to use predefined
configurations, for example default.jfc, but only pay the overhead in the
parser of the events that the stream is listening to. Now all events are
parsed. Workaround is to only enable the events of interest.

- Chunk files not removed
Chunk files may be left behind in the disk repository when the JVM exits.

- EventStream::openFile(...)
Not possible to open a file as an event stream.

- EventStream:::openRepository(...)
Not possible to open a (remote) directory as an event stream.

- EventStream.setReuse(...) (cursor mode)
Method has not been added / implemented.

- EventStream.setParallel(...)
Method has not been added / implemented as it will make most sense if
EventStream::openFile exists.

- EventStream.setOrdered(...)
Method has not been added. Need to figure out how to handle events that 
arrives
way out of order. For example,

  MyEvent event = new MyEvent();
  event.begin();
  event.end(); // end timestamp taken here
  Thread.sleep(1000_000);
  event.commit();

Currently a best effort is made to deliver events in order.

  [1] https://openjdk.java.net/jeps/349
  [2] http://cr.openjdk.java.net/~chegar/docs/sandbox.html
  [3] http://hg.openjdk.java.net/jdk/jdk/raw-file/tip/doc/building.html
  [4] http://cr.openjdk.java.net/~egahlin/health-report-agent/
  [5] 
http://cr.openjdk.java.net/~egahlin/jep-349-preview/docs/jdk/jfr/consumer/RecordingStream.html
  [6] 
http://cr.openjdk.java.net/~egahlin/jep-349-preview/docs/jdk/jfr/consumer/EventStream.html 



More information about the hotspot-jfr-dev mailing list