Welcome to the GCToolKit wiki!
GCToolKit is an API to support the generation of events that represent the data in garbage collection logs. Garbage collection logs contain a journal of all garbage collection events. The tool kit can manage GC logs from JDK 1.4.2 to JDK 17 for the serial, parallel, CMS, iCMS, G1, and Z GC collectors.
The toolkit is partitioned into 3 different modules, API, Parser, and Vertx. The API provides access to the functionality of the toolkit. The parser is responsible for turning raw log lines into JVMEvent objects. The objects are then broadcasted on a message bus. The current implementation of this bus is based on Vert.x. It is the responsibility of the client to provide the implementations for Aggregator/Aggregation pairs. An Aggregation is intended to collect data to provide a unique view of it. An Aggregator listens on the bus and captures the events of interest for the Aggregation.
Aggregator/Aggregation
Below is a sample Aggregator/Aggregation pair that yields a view of total heap occupancy as a time series. The first step is to use an annotation to indicate which event sources the Aggregator is intended for. The constructor contains registrations for the individual events of interest.
@Aggregates({EventSource.G1GC,EventSource.GENERATIONAL,EventSource.ZGC })
public class HeapOccupancyAfterCollection extends Aggregator<HeapOccupancyAfterCollectionAggregation> {
public HeapOccupancyAfterCollection(HeapOccupancyAfterCollectionAggregation results) {
super(results);
// Pair specific event with the methods that will harvest data from the event
register(GenerationalGCPauseEvent.class, this::extractHeapOccupancy);
register(G1GCPauseEvent.class, this::extractHeapOccupancy);
register(ZGCCycle.class,this::extractHeapOccupancy);
register(ShenandoahCycle.class,this::extractHeapOccupancy);
}
// Extract the event type, time stamp and heap occupancy at the end of the collection cycle
private void extractHeapOccupancy(GenerationalGCPauseEvent event) {
aggregation().addDataPoint(event.getGarbageCollectionType(), event.getDateTimeStamp(), event.getHeap().getOccupancyAfterCollection());
}
private void extractHeapOccupancy(G1GCPauseEvent event) {
aggregation().addDataPoint(event.getGarbageCollectionType(), event.getDateTimeStamp(), event.getHeap().getOccupancyAfterCollection());
}
private void extractHeapOccupancy(ZGCCycle event) {
aggregation().addDataPoint(event.getGarbageCollectionType(), event.getDateTimeStamp(), event.getLive().getReclaimEnd());
}
}
/* Annotation to tie implementation with interface. Allows for multiple implementations for each aggregation. */
@Collates(HeapOccupancyAfterCollection.class)
public class HeapOccupancyAfterCollectionSummary implements HeapOccupancyAfterCollectionAggregation {
private HashMap<GarbageCollectionTypes,GCToolKitXYDataSet> aggregations = new HashMap();
public void addDataPoint(GarbageCollectionTypes gcType, DateTimeStamp timeStamp, long heapOccupancy) {
GCToolKitXYDataSet dataSet = aggregations.get(gcType);
if ( dataSet == null) {
dataSet = new GCToolKitXYDataSet();
aggregations.put(gcType,dataSet);
}
dataSet.add(timeStamp.getTimeStamp(),heapOccupancy);
}
public HashMap<GarbageCollectionTypes,GCToolKitXYDataSet> get() {
return aggregations;
}
@Override
public boolean hasWarning() {
return false;
}
@Override
public boolean isEmpty() {
return aggregations.isEmpty();
}
}
Using modules
If the Aggregator/Aggregation is packaged into a Module and exposed as a service provider, the API will pick the implementations and automatically register them. The following is a sample module-info.java implementation.
module gctoolkit.sample {
requires gctoolkit.api;
requires gctoolkit.vertx;
requires java.logging;
exports com.microsoft.gctoolkit.sample.aggregation to gctoolkit.vertx;
provides com.microsoft.gctoolkit.aggregator.Aggregation with com.microsoft.gctoolkit.sample.aggregation.HeapOccupancyAfterCollectionSummary;
}