# HG changeset patch # User shade # Date 1481749539 -3600 # Node ID 8dc27cf89d586442d0938042dbb703e7db547bba # Parent b846cd430ac52e2581764ead7d80321e0d0dbc74 Snapshot rendering. diff -r b846cd430ac5 -r 8dc27cf89d58 src/main/java/org/openjdk/shenandoah/DataProvider.java --- a/src/main/java/org/openjdk/shenandoah/DataProvider.java Wed Dec 14 20:14:55 2016 +0100 +++ b/src/main/java/org/openjdk/shenandoah/DataProvider.java Wed Dec 14 22:05:39 2016 +0100 @@ -2,6 +2,9 @@ import sun.jvmstat.monitor.*; +import java.util.ArrayList; +import java.util.List; + public class DataProvider { private final int maxRegions; @@ -30,15 +33,15 @@ } } - public int maxRegions() { - return maxRegions; + public Snapshot snapshot() { + List stats = new ArrayList<>(); + for (LongMonitor m : data) { + stats.add(new RegionStat(maxSize, m.longValue())); + } + boolean isMarking = (status.longValue() & 0x1) > 0; + boolean isEvacuating = (status.longValue() & 0x2) > 0; + + return new Snapshot(System.currentTimeMillis(), stats, isMarking, isEvacuating); } - public long status() { - return status.longValue(); - } - - public RegionStat regionStat(int i) { - return new RegionStat(maxSize, data[i].longValue()); - } } diff -r b846cd430ac5 -r 8dc27cf89d58 src/main/java/org/openjdk/shenandoah/RegionStat.java --- a/src/main/java/org/openjdk/shenandoah/RegionStat.java Wed Dec 14 20:14:55 2016 +0100 +++ b/src/main/java/org/openjdk/shenandoah/RegionStat.java Wed Dec 14 22:05:39 2016 +0100 @@ -68,5 +68,31 @@ g.drawRect(x, y, width, height); } + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + RegionStat that = (RegionStat) o; + + if (unused != that.unused) return false; + if (humongous != that.humongous) return false; + if (inCset != that.inCset) return false; + if (Double.compare(that.liveLvl, liveLvl) != 0) return false; + return Double.compare(that.usedLvl, usedLvl) == 0; + } + + @Override + public int hashCode() { + int result; + long temp; + result = (unused ? 1 : 0); + result = 31 * result + (humongous ? 1 : 0); + result = 31 * result + (inCset ? 1 : 0); + temp = Double.doubleToLongBits(liveLvl); + result = 31 * result + (int) (temp ^ (temp >>> 32)); + temp = Double.doubleToLongBits(usedLvl); + result = 31 * result + (int) (temp ^ (temp >>> 32)); + return result; + } } diff -r b846cd430ac5 -r 8dc27cf89d58 src/main/java/org/openjdk/shenandoah/ShenandoahVisualizer.java --- a/src/main/java/org/openjdk/shenandoah/ShenandoahVisualizer.java Wed Dec 14 20:14:55 2016 +0100 +++ b/src/main/java/org/openjdk/shenandoah/ShenandoahVisualizer.java Wed Dec 14 22:05:39 2016 +0100 @@ -50,38 +50,6 @@ } } - static class StatusPanel extends JPanel { - private final DataProvider data; - - public StatusPanel(DataProvider data) { - this.data = data; - } - - public void paint(Graphics g) { - boolean isMarking = (data.status() & 0x1) > 0; - boolean isEvacuating = (data.status() & 0x2) > 0; - - g.setColor(Color.BLACK); - g.drawString("marking:", 0, 15); - if (isMarking) { - g.setColor(Color.RED); - } else { - g.setColor(Color.GREEN); - } - g.fillRect(60, 0, 40, 20); - - g.setColor(Color.BLACK); - g.drawString("evacuating:", 120, 15); - if (isEvacuating) { - g.setColor(Color.RED); - } else { - g.setColor(Color.GREEN); - } - g.fillRect(220, 0, 40, 20); - - } - } - static class VisPanelListener extends ComponentAdapter { public void componentResized(ComponentEvent ev) { width = ev.getComponent().getWidth(); @@ -97,22 +65,21 @@ DataProvider data = new DataProvider(args[0]); - VisPanel p = new VisPanel(); p.addComponentListener(new VisPanelListener()); - StatusPanel statusPanel = new StatusPanel(data); - statusPanel.setPreferredSize(new Dimension(220, 20)); - JFrame frame = new JFrame(); frame.getContentPane().add(p, BorderLayout.CENTER); - frame.getContentPane().add(statusPanel, BorderLayout.SOUTH); frame.setSize(INITIAL_WIDTH, INITIAL_HEIGHT); frame.setVisible(true); ScheduledExecutorService service = Executors.newScheduledThreadPool(1); service.scheduleAtFixedRate(() -> { - render(data); + Snapshot cur = data.snapshot(); + if (!cur.equals(lastSnapshot)) { + render(cur); + lastSnapshot = cur; + } frame.repaint(); }, 0, 100, TimeUnit.MILLISECONDS); @@ -124,20 +91,51 @@ }); } - public static void render(DataProvider data) { - int cols = (int) Math.floor(Math.sqrt(data.maxRegions())); - int rows = (int) Math.floor(data.maxRegions() / cols); + static volatile Snapshot lastSnapshot; + + public static void render(Snapshot snapshot) { + int cols = (int) Math.floor(Math.sqrt(snapshot.regionCount())); + int rows = (int) Math.floor(snapshot.regionCount() / cols); BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); - int rectWidth = img.getWidth() / cols; - int rectHeight = img.getHeight() / rows; Graphics g = img.getGraphics(); - for (int i = 0; i < data.maxRegions(); i++) { - int rectx = (i % cols) * rectWidth; - int recty = (i / rows) * rectHeight; + + final int PAD = 20; + final int LINE = 30; + final int PAD_TOP = 100; + + // Draw white background + g.setColor(Color.WHITE); + g.fillRect(0, 0, width, height); + + // Draw time + g.setColor(Color.BLACK); + g.drawString(String.valueOf(snapshot.time()), PAD, PAD); - RegionStat s = data.regionStat(i); + // Draw status + g.setColor(Color.BLACK); + String status = ""; + if (snapshot.isMarking()) { + status += " (marking)"; + } + if (snapshot.isEvacuating()) { + status += " (evacuating)"; + } + if (status.isEmpty()) { + status = " (idle)"; + } + g.drawString("Status: " + status, PAD, PAD + 1 * LINE); + + // Draw region field + int rectWidth = (img.getWidth() - 2*PAD) / cols; + int rectHeight = (img.getHeight() - (PAD + PAD_TOP)) / rows; + + for (int i = 0; i < snapshot.regionCount(); i++) { + int rectx = PAD + (i % cols) * rectWidth; + int recty = PAD + PAD_TOP + (i / rows) * rectHeight; + + RegionStat s = snapshot.get(i); s.render(g, rectx, recty, rectWidth, rectHeight); } g.dispose(); diff -r b846cd430ac5 -r 8dc27cf89d58 src/main/java/org/openjdk/shenandoah/Snapshot.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/main/java/org/openjdk/shenandoah/Snapshot.java Wed Dec 14 22:05:39 2016 +0100 @@ -0,0 +1,58 @@ +package org.openjdk.shenandoah; + +import java.util.List; + +public class Snapshot { + + private final long time; + private final List stats; + private final boolean isMarking; + private final boolean isEvacuating; + + public Snapshot(long time, List stats, boolean isMarking, boolean isEvacuating) { + this.time = time; + this.stats = stats; + this.isMarking = isMarking; + this.isEvacuating = isEvacuating; + } + + public boolean isMarking() { + return isMarking; + } + + public boolean isEvacuating() { + return isEvacuating; + } + + public RegionStat get(int i) { + return stats.get(i); + } + + public long time() { + return time; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + Snapshot snapshot = (Snapshot) o; + + if (isMarking != snapshot.isMarking) return false; + if (isEvacuating != snapshot.isEvacuating) return false; + return stats != null ? stats.equals(snapshot.stats) : snapshot.stats == null; + } + + @Override + public int hashCode() { + int result = stats.hashCode(); + result = 31 * result + (isMarking ? 1 : 0); + result = 31 * result + (isEvacuating ? 1 : 0); + return result; + } + + public int regionCount() { + return stats.size(); + } +}