/* * Copyright (c) 2013-2017 Chris Newland. * Licensed under https://github.com/AdoptOpenJDK/jitwatch/blob/master/LICENSE-BSD * Instructions: https://github.com/AdoptOpenJDK/jitwatch/wiki */ package org.adoptopenjdk.jitwatch.ui.graphing; import static org.adoptopenjdk.jitwatch.util.UserInterfaceUtil.fix; import java.util.Collections; import java.util.Comparator; import java.util.List; import org.adoptopenjdk.jitwatch.model.CodeCacheEvent; import org.adoptopenjdk.jitwatch.model.Tag; import org.adoptopenjdk.jitwatch.ui.main.JITWatchUI; import org.adoptopenjdk.jitwatch.util.UserInterfaceUtil; import javafx.scene.Scene; import javafx.scene.layout.StackPane; import javafx.scene.paint.Color; public class CodeCacheStage extends AbstractGraphStage { private boolean labelLeft = true; public CodeCacheStage(JITWatchUI parent) { super(parent, JITWatchUI.WINDOW_WIDTH, JITWatchUI.WINDOW_HEIGHT, true); StackPane root = new StackPane(); Scene scene = UserInterfaceUtil.getScene(root, width, height); canvas.widthProperty().bind(root.widthProperty()); canvas.heightProperty().bind(root.heightProperty()); root.getChildren().add(canvas); setTitle("JITWatch Free Code Cache"); setScene(scene); show(); redraw(); } @Override public final void redraw() { super.baseRedraw(); labelLeft = true; List<CodeCacheEvent> codeCacheEvents = mainUI.getJITDataModel().getCodeCacheEvents(); Collections.sort(codeCacheEvents, new Comparator<CodeCacheEvent>() { @Override public int compare(CodeCacheEvent e1, CodeCacheEvent e2) { return Long.compare(e1.getStamp(), e2.getStamp()); } }); if (codeCacheEvents.size() > 0) { CodeCacheEvent firstEvent = codeCacheEvents.get(0); minX = firstEvent.getStamp(); Tag endOfLogTag = mainUI.getJITDataModel().getEndOfLogTag(); if (endOfLogTag != null) { maxX = getStampFromTag(endOfLogTag); } else { CodeCacheEvent lastEvent = codeCacheEvents.get(codeCacheEvents.size() - 1); maxX = lastEvent.getStamp(); } minY = firstEvent.getFreeCodeCache(); maxY = firstEvent.getFreeCodeCache(); // find ranges for (CodeCacheEvent event : codeCacheEvents) { long freeCodeCache = event.getFreeCodeCache(); if (freeCodeCache > 0) { if (freeCodeCache > maxY) { maxY = freeCodeCache; } else if (freeCodeCache < minY) { minY = freeCodeCache; } } } drawAxes(); double lastCX = graphGapLeft + normaliseX(minX); double lastCY = graphGapTop + normaliseY(firstEvent.getFreeCodeCache()); Color colourLine = Color.BLUE; double lineWidth = 2.0; for (CodeCacheEvent event : codeCacheEvents) { long stamp = event.getStamp(); double x = graphGapLeft + normaliseX(stamp); double y = lastCY; switch (event.getEventType()) { case COMPILATION: y = addToGraph(lastCX, lastCY, colourLine, lineWidth, event, x); break; case SWEEPER: y = addToGraph(lastCX, lastCY, colourLine, lineWidth, event, x); showLabel("Sweep", Color.WHITE, x, y); break; case CACHE_FULL: showLabel("Code Cache Full", Color.RED, x, y); break; } lastCY = y; lastCX = x; } continueLineToEndOfXAxis(lastCX, lastCY, colourLine, lineWidth); } else { gc.fillText("No code cache information in log", fix(10), fix(10)); } } private double addToGraph(double lastCX, double lastCY, Color colourLine, double lineWidth, CodeCacheEvent event, double x) { long freeCodeCache = event.getFreeCodeCache(); double y = graphGapTop + normaliseY(freeCodeCache); gc.setFill(colourLine); gc.setStroke(colourLine); gc.setLineWidth(lineWidth); gc.strokeLine(fix(lastCX), fix(lastCY), fix(x), fix(y)); return y; } private void showLabel(String text, Color background, double x, double y) { double labelX; double labelY; if (labelLeft) { labelX = x - getApproximateStringWidth(text) - 16; labelY = Math.min(y - getStringHeight(), graphGapTop + chartHeight - 32); } else { labelX = x + 8; labelY = Math.min(y, graphGapTop + chartHeight - 32); } drawLabel(text, labelX, labelY, background); labelLeft = !labelLeft; } }