org.adoptopenjdk.jitwatch.jarscan.visualiser.HistoPlotter Maven / Gradle / Ivy
/*
* Copyright (c) 2016-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.jarscan.visualiser;
import java.awt.image.RenderedImage;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Method;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import javax.imageio.ImageIO;
import org.adoptopenjdk.jitwatch.util.UserInterfaceUtil;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.SnapshotParameters;
import javafx.scene.chart.Axis;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.ScatterChart;
import javafx.scene.chart.XYChart;
import javafx.scene.chart.XYChart.Series;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.control.Tooltip;
import javafx.scene.image.WritableImage;
import javafx.scene.input.KeyEvent;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;
import javafx.stage.WindowEvent;
public class HistoPlotter extends Application
{
private List> values = new ArrayList<>();
private Scene scene;
private ScatterChart chart;
private int limit = -1;
private static final String PARAM_SCREENSHOT = "screenshot";
private static final String PARAM_LIMIT = "limit";
private String screenshotFilename;
private String filename;
public HistoPlotter()
{
}
@Override
public void init() throws Exception
{
super.init();
List lines = new ArrayList<>();
try
{
Parameters parameters = getParameters();
List unnamedParameters = parameters.getUnnamed();
filename = unnamedParameters.get(0);
lines = Files.readAllLines(Paths.get(filename), StandardCharsets.UTF_8);
Map namedParameters = parameters.getNamed();
if (namedParameters.containsKey(PARAM_SCREENSHOT))
{
screenshotFilename = namedParameters.get(PARAM_SCREENSHOT);
}
if (namedParameters.containsKey(PARAM_LIMIT))
{
limit = Integer.parseInt(namedParameters.get(PARAM_LIMIT));
}
}
catch (IOException e)
{
e.printStackTrace();
}
int maxSize = 0;
for (String line : lines)
{
String[] parts = line.split(",");
if (parts.length == 2)
{
Number xValue = Integer.parseInt(parts[0]);
Number yValue = Integer.parseInt(parts[1]);
maxSize = Math.max(maxSize, xValue.intValue());
XYChart.Data point = new XYChart.Data(xValue, yValue);
values.add(point);
}
}
if (limit == -1)
{
limit = maxSize;
}
}
private void updateObservable()
{
chart.getData().clear();
ObservableList> observableValues = FXCollections.observableArrayList();
for (XYChart.Data value : values)
{
if (value.getXValue().intValue() <= limit)
{
observableValues.add(value);
}
}
XYChart.Series series = new XYChart.Series<>(observableValues);
series.setName("Method Sizes");
chart.getData().add(series);
for (Series chartSeries : chart.getData())
{
for (final XYChart.Data data : chartSeries.getData())
{
Tooltip tooltip = new Tooltip();
tooltip.setText(data.getYValue().toString() + " instances of value " + data.getXValue().toString());
Tooltip.install(data.getNode(), tooltip);
}
}
chart.setTitle(getTitle());
}
private void doScreenshot()
{
if (screenshotFilename != null)
{
WritableImage imageSnap = new WritableImage((int) chart.getWidth(), (int) chart.getHeight());
chart.snapshot(new SnapshotParameters(), imageSnap);
try
{
Class> swingFXUtils = Class.forName("javafx.embed.swing.SwingFXUtils");
Method methodFromFXImage = swingFXUtils.getMethod("fromFXImage", new Class[] {
javafx.scene.image.Image.class,
java.awt.image.BufferedImage.class });
ImageIO.write((RenderedImage) methodFromFXImage.invoke(null, new Object[] {
imageSnap,
null }), "png", new File(screenshotFilename));
Platform.exit();
}
catch (Throwable t)
{
System.err.println("Couldn't write screenshot");
t.printStackTrace();
}
}
}
public HistoPlotter(String[] args)
{
if (args.length < 1)
{
System.err
.println("HistoPlotter [--" + PARAM_LIMIT + "=limit] [--" + PARAM_SCREENSHOT + "=outputFilename]");
System.exit(-1);
}
launch(args);
}
@Override
public void start(final Stage stage)
{
stage.setOnCloseRequest(new EventHandler()
{
@Override
public void handle(WindowEvent arg0)
{
stage.close();
}
});
stage.addEventHandler(WindowEvent.WINDOW_SHOWN, new EventHandler()
{
@Override
public void handle(WindowEvent window)
{
doScreenshot();
}
});
BorderPane borderPane = new BorderPane();
Label label = new Label("Limit:");
final TextField tfLimit = new TextField();
tfLimit.setText(Integer.toString(limit));
tfLimit.setOnKeyReleased(new EventHandler()
{
@Override
public void handle(KeyEvent keyEvent)
{
try
{
limit = Integer.parseInt(tfLimit.getText());
updateObservable();
}
catch (NumberFormatException nfe)
{
}
}
});
HBox hBox = new HBox();
hBox.getChildren().addAll(label, tfLimit);
hBox.setSpacing(10);
scene = UserInterfaceUtil.getScene(borderPane, 800, 480);
borderPane.setTop(hBox);
borderPane.setCenter(buildChart());
updateObservable();
stage.setTitle("JarScan Histo Plotter by @chriswhocodes");
stage.setScene(scene);
stage.show();
}
private String getTitle()
{
String chartTitle = null;
int lastSlash = filename.lastIndexOf(File.separator);
if (lastSlash != -1)
{
chartTitle = filename.substring(lastSlash + 1);
}
else
{
chartTitle = filename;
}
return "Input file: " + chartTitle + " limit: " + limit;
}
private ScatterChart buildChart()
{
Axis xAxis = new NumberAxis();
xAxis.setLabel("Method bytecode size (bytes)");
Axis yAxis = new NumberAxis();
yAxis.setLabel("Frequency");
chart = new ScatterChart<>(xAxis, yAxis);
chart.setAnimated(false);
chart.setLegendVisible(false);
chart.setPadding(new Insets(10, 20, 10, 10));
chart.setTitle(getTitle());
return chart;
}
public static void main(String[] args)
{
new HistoPlotter(args);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy