diff --git a/build.properties b/build.properties index 2d48fba9..2da9394b 100644 --- a/build.properties +++ b/build.properties @@ -1 +1 @@ -version=1.2.1 +version=1.2.2 diff --git a/core/pom.xml b/core/pom.xml index 0715a76a..a696da8d 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -4,7 +4,7 @@ com.chrisnewland jitwatch-parent - 1.2.1 + 1.2.2 jitwatch-core diff --git a/core/src/main/resources/examples/LoopUnroll.java b/core/src/main/resources/examples/LoopUnroll.java new file mode 100644 index 00000000..9aef9926 --- /dev/null +++ b/core/src/main/resources/examples/LoopUnroll.java @@ -0,0 +1,189 @@ + +public class LoopUnroll +{ + private static final int MAX = 1_000_000; + + private long[] data = new long[MAX]; + + public LoopUnroll() + { + createData(); + + long total = 0; + + total += constantStride1Int(); + total += constantStride2Int(); + total += constantStride4Int(); + total += constantStride8Int(); + total += constantStride16Int(); + total += variableStrideInt(1); + total += constantStride1Long(); + total += constantStride1IntWithExit(); + total += constantStride1IntWith2Exits(); + total += constantStride1IntWith4Exits(); + + System.out.println("Total: " + total); + } + + private void createData() + { + java.util.Random random = new java.util.Random(); + + for (int i = 0; i < MAX; i++) + { + data[i] = random.nextLong(); + } + } + + private long constantStride1Int() + { + long sum = 0; + for (int i = 0; i < MAX; i += 1) + { + sum += data[i]; + } + return sum; + } + + private long constantStride2Int() + { + long sum = 0; + for (int i = 0; i < MAX; i += 2) + { + sum += data[i]; + } + return sum; + } + + private long constantStride4Int() + { + long sum = 0; + for (int i = 0; i < MAX; i += 4) + { + sum += data[i]; + } + return sum; + } + + private long constantStride8Int() + { + long sum = 0; + for (int i = 0; i < MAX; i += 8) + { + sum += data[i]; + } + return sum; + } + + private long constantStride16Int() + { + long sum = 0; + for (int i = 0; i < MAX; i += 16) + { + sum += data[i]; + } + return sum; + } + + private long variableStrideInt(int stride) + { + long sum = 0; + for (int i = 0; i < MAX; i += stride) + { + sum += data[i]; + } + return sum; + } + + private long constantStride1Long() + { + long sum = 0; + for (long l = 0; l < MAX; l++) + { + // cast because array index can't be longer than int + sum += data[(int) l]; + } + return sum; + } + + // NICE !!! unrolls with test on each unroll :) + private long constantStride1IntWithExit() + { + long sum = 0; + + for (int i = 0; i < MAX; i += 1) + { + if (data[i] == 0x1234) + { + break; + } + else + { + sum += data[i]; + } + } + + return sum; + } + + // NICE !!! unrolls with test on each unroll :) + private long constantStride1IntWith2Exits() + { + long sum = 0; + + for (int i = 0; i < MAX; i += 1) + { + if (data[i] == 0x1234) + { + break; + } + else if (data[i] == 0x5678) + { + break; + } + else + { + sum += data[i]; + } + } + + return sum; + } + + // NICE !!! unrolls with test on each unroll :) + private long constantStride1IntWith4Exits() + { + long sum = 0; + + for (int i = 0; i < MAX; i += 1) + { + if (data[i] == 0x1234) + { + break; + } + else if (data[i] == 0x5678) + { + break; + } + else if (data[i] == 0x9ABC) + { + break; + } + else if (data[i] == 0xDEF0) + { + break; + } + else + { + sum += data[i]; + } + } + + return sum; + } + + public static void main(String[] args) + { + new LoopUnroll(); + } +} diff --git a/pom.xml b/pom.xml index eb5734c8..e2ef929f 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ com.chrisnewland jitwatch-parent - 1.2.1 + 1.2.2 UTF-8 diff --git a/ui/pom.xml b/ui/pom.xml index e4c12103..7f7e072b 100644 --- a/ui/pom.xml +++ b/ui/pom.xml @@ -4,7 +4,7 @@ com.chrisnewland jitwatch-parent - 1.2.1 + 1.2.2 jitwatch-ui diff --git a/ui/src/main/java/org/adoptopenjdk/jitwatch/ui/compilechain/CompileChainStage.java b/ui/src/main/java/org/adoptopenjdk/jitwatch/ui/compilechain/CompileChainStage.java index 3501e674..e7da7819 100644 --- a/ui/src/main/java/org/adoptopenjdk/jitwatch/ui/compilechain/CompileChainStage.java +++ b/ui/src/main/java/org/adoptopenjdk/jitwatch/ui/compilechain/CompileChainStage.java @@ -23,10 +23,14 @@ import javafx.event.EventHandler; import javafx.scene.Scene; +import javafx.scene.control.Button; import javafx.scene.control.ScrollPane; import javafx.scene.control.Tooltip; import javafx.scene.input.MouseEvent; +import javafx.scene.layout.HBox; import javafx.scene.layout.Pane; +import javafx.scene.layout.Priority; +import javafx.scene.layout.Region; import javafx.scene.layout.VBox; import javafx.scene.paint.Color; import javafx.scene.shape.Line; @@ -80,12 +84,24 @@ public CompileChainStage(IMemberSelectedListener selectionListener, final IStage scrollPane.setContent(pane); compilationChooser = new CompilationChooser(selectionListener); - + VBox verticalLayout = new VBox(); - - verticalLayout.getChildren().addAll(compilationChooser.getCombo(), scrollPane); - + Scene scene = UserInterfaceUtil.getScene(verticalLayout, JITWatchUI.WINDOW_WIDTH, JITWatchUI.WINDOW_HEIGHT); + + Region spacer = new Region(); + HBox.setHgrow(spacer, Priority.ALWAYS); + + Button buttonSnapShot = UserInterfaceUtil.getSnapshotButton(scene, "CompileChain"); + + HBox hBox = new HBox(); + + hBox.getChildren().add(compilationChooser.getCombo()); + hBox.getChildren().add(spacer); + hBox.getChildren().add(buttonSnapShot); + + verticalLayout.getChildren().addAll(hBox, scrollPane); + RateLimitedResizeListener resizeListener = new RateLimitedResizeListener(this, 200); diff --git a/ui/src/main/java/org/adoptopenjdk/jitwatch/ui/main/JITWatchUI.java b/ui/src/main/java/org/adoptopenjdk/jitwatch/ui/main/JITWatchUI.java index 94c060b6..94bf25c5 100644 --- a/ui/src/main/java/org/adoptopenjdk/jitwatch/ui/main/JITWatchUI.java +++ b/ui/src/main/java/org/adoptopenjdk/jitwatch/ui/main/JITWatchUI.java @@ -832,7 +832,9 @@ public void changed(ObservableValue arg0, Compila lblHeap.setStyle(labelStyle); lblVmVersion.setStyle(labelStyle); - + + Button buttonSnapShot = UserInterfaceUtil.getSnapshotButton(scene, "JITWatch"); + hboxBottom.setPadding(new Insets(4)); hboxBottom.setPrefHeight(statusBarHeight); hboxBottom.setSpacing(4); @@ -844,6 +846,7 @@ public void changed(ObservableValue arg0, Compila hboxBottom.getChildren().add(lblTweakLog); hboxBottom.getChildren().add(springRight); hboxBottom.getChildren().add(lblVmVersion); + hboxBottom.getChildren().add(buttonSnapShot); borderPane.setTop(hboxTop); borderPane.setCenter(spMain); diff --git a/ui/src/main/java/org/adoptopenjdk/jitwatch/ui/sandbox/SandboxStage.java b/ui/src/main/java/org/adoptopenjdk/jitwatch/ui/sandbox/SandboxStage.java index cdee6d45..038f2ade 100644 --- a/ui/src/main/java/org/adoptopenjdk/jitwatch/ui/sandbox/SandboxStage.java +++ b/ui/src/main/java/org/adoptopenjdk/jitwatch/ui/sandbox/SandboxStage.java @@ -65,6 +65,8 @@ import javafx.scene.control.TextArea; import javafx.scene.layout.BorderPane; import javafx.scene.layout.HBox; +import javafx.scene.layout.Priority; +import javafx.scene.layout.Region; import javafx.scene.layout.VBox; import javafx.stage.FileChooser; import javafx.stage.Stage; @@ -299,7 +301,11 @@ public void handle(ActionEvent e) showOutput(outputString); } }); + + BorderPane borderPane = new BorderPane(); + Scene scene = UserInterfaceUtil.getScene(borderPane, JITWatchUI.WINDOW_WIDTH, JITWatchUI.WINDOW_HEIGHT); + HBox hBoxTools = new HBox(); hBoxTools.setSpacing(10); @@ -312,7 +318,15 @@ public void handle(ActionEvent e) hBoxTools.getChildren().add(btnResetSandbox); hBoxTools.getChildren().add(comboBoxVMLanguage); hBoxTools.getChildren().add(btnRun); - hBoxTools.getChildren().add(btnOutput); + hBoxTools.getChildren().add(btnOutput); + + Region spacer = new Region(); + HBox.setHgrow(spacer, Priority.ALWAYS); + + Button buttonSnapShot = UserInterfaceUtil.getSnapshotButton(scene, "Sandbox"); + + hBoxTools.getChildren().add(spacer); + hBoxTools.getChildren().add(buttonSnapShot); splitVertical.getItems().add(tabPane); splitVertical.getItems().add(taLog); @@ -323,14 +337,11 @@ public void handle(ActionEvent e) vBoxMain.getChildren().add(hBoxTools); vBoxMain.getChildren().add(splitVertical); - BorderPane borderPane = new BorderPane(); borderPane.setTop(hBoxTools); borderPane.setCenter(splitVertical); initialiseLog(); - Scene scene = UserInterfaceUtil.getScene(borderPane, JITWatchUI.WINDOW_WIDTH, JITWatchUI.WINDOW_HEIGHT); - setScene(scene); setOnCloseRequest(new EventHandler() diff --git a/ui/src/main/java/org/adoptopenjdk/jitwatch/ui/triview/TriView.java b/ui/src/main/java/org/adoptopenjdk/jitwatch/ui/triview/TriView.java index d301e1c9..17d51f5d 100644 --- a/ui/src/main/java/org/adoptopenjdk/jitwatch/ui/triview/TriView.java +++ b/ui/src/main/java/org/adoptopenjdk/jitwatch/ui/triview/TriView.java @@ -109,7 +109,7 @@ public class TriView extends Stage implements ILineListener, ICompilationChangeL private CompilationInfo compilationInfo; - private Label lblMemberInfo; + private Label lblStatusBar; private boolean ignoreComboChanged = false; @@ -122,7 +122,7 @@ public class TriView extends Stage implements ILineListener, ICompilationChangeL private TriViewNavigationStack navigationStack; private IReadOnlyJITDataModel model; - + private boolean selectedProgrammatically = false; public TriView(final JITWatchUI parent, final JITWatchConfig config) @@ -252,7 +252,7 @@ public void changed(ObservableValue ov, IMetaMember oldMe if (!ignoreComboChanged) { if (newMember != null) - { + { if (!selectedProgrammatically) { memberSelectionListener.selectMember(newMember, true, true); @@ -303,12 +303,21 @@ public IMetaMember fromString(String arg0) splitViewer.prefHeightProperty().bind(vBox.heightProperty()); - lblMemberInfo = new Label(); + lblStatusBar = new Label(); + + Button buttonSnapShot = UserInterfaceUtil.getSnapshotButton(scene, "TriView"); + + Region spacerStatus = new Region(); + HBox.setHgrow(spacerStatus, Priority.ALWAYS); + + HBox hBoxStatusBar = new HBox(); + hBoxStatusBar.setSpacing(16.0); + hBoxStatusBar.getChildren().addAll(lblStatusBar, spacerStatus, buttonSnapShot); vBox.getChildren().add(hBoxToolBarClass); vBox.getChildren().add(hBoxToolBarButtons); vBox.getChildren().add(splitViewer); - vBox.getChildren().add(lblMemberInfo); + vBox.getChildren().add(hBoxStatusBar); setScene(scene); @@ -520,7 +529,7 @@ public void setMetaClass(MetaClass metaClass) if (!members.isEmpty()) { IMetaMember firstMember = members.get(0); - + if (!selectedProgrammatically) { memberSelectionListener.selectMember(firstMember, true, true); @@ -553,15 +562,15 @@ public void setMember(IMetaMember member, boolean force, int highlightBCI) } public void setMember(final IMetaMember member, boolean force, final boolean jumpToSource, final int highlightBCI) - { + { selectedProgrammatically = true; if (member == null) { clear(); - + selectedProgrammatically = false; - + return; } @@ -629,10 +638,10 @@ public void setMember(final IMetaMember member, boolean force, final boolean jum applyActionsIfOffsetMismatchDetected(statusBarBuilder); - lblMemberInfo.setText(statusBarBuilder.toString()); + lblStatusBar.setText(statusBarBuilder.toString()); updateBytecodeAndAssembly(jumpToSource, highlightBCI); - + selectedProgrammatically = false; } @@ -730,7 +739,7 @@ private void updateBytecodeAndAssembly(boolean focusSource, int highlightBCI) compilationInfo.setBytecodeSize(Integer.toString(memberBytecode.size())); } - lblMemberInfo.setText(S_EMPTY); + lblStatusBar.setText(S_EMPTY); } } @@ -796,7 +805,7 @@ public void clear() classSearch.clear(); - lblMemberInfo.setText(S_EMPTY); + lblStatusBar.setText(S_EMPTY); updateButtons(); } diff --git a/ui/src/main/java/org/adoptopenjdk/jitwatch/util/UserInterfaceUtil.java b/ui/src/main/java/org/adoptopenjdk/jitwatch/util/UserInterfaceUtil.java index c3a969c8..214da45d 100644 --- a/ui/src/main/java/org/adoptopenjdk/jitwatch/util/UserInterfaceUtil.java +++ b/ui/src/main/java/org/adoptopenjdk/jitwatch/util/UserInterfaceUtil.java @@ -5,22 +5,26 @@ */ package org.adoptopenjdk.jitwatch.util; +import java.io.File; import java.io.InputStream; import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.text.SimpleDateFormat; +import java.util.Date; import java.util.HashMap; -import java.util.List; -import org.adoptopenjdk.jitwatch.model.IMetaMember; -import org.adoptopenjdk.jitwatch.model.IReadOnlyJITDataModel; import org.adoptopenjdk.jitwatch.model.bytecode.BCAnnotationType; -import org.adoptopenjdk.jitwatch.model.bytecode.ClassBC; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import javafx.application.Platform; +import javafx.event.ActionEvent; +import javafx.event.EventHandler; import javafx.scene.Parent; import javafx.scene.Scene; +import javafx.scene.control.Button; import javafx.scene.image.Image; +import javafx.scene.image.ImageView; +import javafx.scene.image.WritableImage; import javafx.scene.paint.Color; import javafx.scene.text.Font; @@ -31,9 +35,12 @@ public final class UserInterfaceUtil // https://www.iconfinder.com/icons/173960/tick_icon#size=16 public static final Image IMAGE_TICK; + public static final Image IMAGE_CAMERA; + public static final String FONT_MONOSPACE_FAMILY; public static final String FONT_MONOSPACE_SIZE; - public static final boolean ADD_CLOSE_DECORATION; // for fullscreen JavaFX systems + public static final boolean ADD_CLOSE_DECORATION; // for fullscreen JavaFX + // systems private UserInterfaceUtil() { @@ -42,6 +49,7 @@ private UserInterfaceUtil() static { IMAGE_TICK = loadResource("/images/tick.png"); + IMAGE_CAMERA = loadResource("/images/camera.png"); FONT_MONOSPACE_FAMILY = System.getProperty("monospaceFontFamily", Font.font(java.awt.Font.MONOSPACED, 12).getName()); FONT_MONOSPACE_SIZE = System.getProperty("monospaceFontSize", "12"); @@ -68,6 +76,60 @@ private static Image loadResource(String path) return result; } + public static Button getSnapshotButton(final Scene scene, final String filenamePrefix) + { + Button buttonSnapShot = new Button(); + + Image image = UserInterfaceUtil.IMAGE_CAMERA; + + buttonSnapShot.setGraphic(new ImageView(image)); + + buttonSnapShot.setOnAction(new EventHandler() + { + @Override + public void handle(ActionEvent e) + { + takeSnapShot(scene, filenamePrefix); + } + }); + + return buttonSnapShot; + } + + private static void takeSnapShot(Scene scene, String filenamePrefix) + { + WritableImage imageSnap = new WritableImage((int) scene.getWidth(), (int) scene.getHeight()); + + scene.snapshot(imageSnap); + + SimpleDateFormat sfd = new SimpleDateFormat("yyyy.MM.dd.HH.mm.ss"); + + try + { + String snapshotFilename = filenamePrefix + "-snapshot-" + sfd.format(new Date()) + ".png"; + + Class classImageIO = Class.forName("javax.imageio.ImageIO"); + + Class classSwingFXUtils = Class.forName("javafx.embed.swing.SwingFXUtils"); + + Method methodWrite = classImageIO.getMethod("write", + new Class[] { java.awt.image.RenderedImage.class, String.class, File.class }); + + Method methodFromFXImage = classSwingFXUtils.getMethod("fromFXImage", + new Class[] { javafx.scene.image.Image.class, java.awt.image.BufferedImage.class }); + + methodWrite.invoke(null, + new Object[] { + methodFromFXImage.invoke(null, new Object[] { imageSnap, null }), + "png", + new File(snapshotFilename) }); + } + catch (Throwable t) + { + logger.error("Could not create snapshot", t); + } + } + public static Scene getScene(Parent rootNode, double width, double height) { Scene scene = new Scene(rootNode, width, height); diff --git a/ui/src/main/resources/images/camera.png b/ui/src/main/resources/images/camera.png new file mode 100755 index 00000000..5f818d25 Binary files /dev/null and b/ui/src/main/resources/images/camera.png differ