Skip to content

Commit 536ba64

Browse files
committed
Several follow ups for #61
- In the "recent" menu, show shortened description for GcSeries - Added calculation of start date to GCModel - Fixed error when loading a GcSeries via Commandline - Other smaller improvements
1 parent 7a5b5a3 commit 536ba64

File tree

10 files changed

+238
-70
lines changed

10 files changed

+238
-70
lines changed

src/main/java/com/tagtraum/perf/gcviewer/GCViewer.java

+13-2
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,24 @@ public class GCViewer {
2626
private static final int EXIT_OK = 0;
2727
private static final int EXIT_EXPORT_FAILED = -1;
2828
private static final int EXIT_ARGS_PARSE_FAILED = -2;
29+
private GCViewerGuiController gcViewerGuiController;
30+
private GCViewerArgsParser gcViewerArgsParser;
31+
32+
public GCViewer() {
33+
this(new GCViewerGuiController(), new GCViewerArgsParser());
34+
}
35+
36+
public GCViewer(GCViewerGuiController gcViewerGuiController, GCViewerArgsParser gcViewerArgsParser) {
37+
this.gcViewerGuiController = gcViewerGuiController;
38+
this.gcViewerArgsParser = gcViewerArgsParser;
39+
}
2940

3041
public static void main(final String[] args) throws InvocationTargetException, InterruptedException {
3142
new GCViewer().doMain(args);
3243
}
3344

3445
public void doMain(String[] args) throws InvocationTargetException, InterruptedException {
35-
GCViewerArgsParser argsParser = new GCViewerArgsParser();
46+
GCViewerArgsParser argsParser = gcViewerArgsParser;
3647
try {
3748
argsParser.parseArguments(args);
3849
}
@@ -64,7 +75,7 @@ else if (argsParser.getArgumentCount() >= 2) {
6475
}
6576
}
6677
else {
67-
new GCViewerGuiController().startGui(argsParser.getArgumentCount() == 1 ? argsParser.getGcResource() : null);
78+
gcViewerGuiController.startGui(argsParser.getArgumentCount() == 1 ? argsParser.getGcResource() : null);
6879
}
6980
}
7081

src/main/java/com/tagtraum/perf/gcviewer/ctrl/impl/GCModelSeriesLoaderImpl.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,6 @@ public GCResource getGcResource() {
2828

2929
@Override
3030
protected GCModel loadGcModel() throws DataReaderException {
31-
return dataReaderFacade.loadModelFromSeries(gcResourceSeries);
31+
return dataReaderFacade.loadModel(gcResourceSeries);
3232
}
3333
}

src/main/java/com/tagtraum/perf/gcviewer/imp/DataReaderFacade.java

+4-1
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,9 @@ public GCModel loadModel(GCResource gcResource) throws DataReaderException {
5252
if (gcResource == null) {
5353
throw new NullPointerException("gcResource must never be null");
5454
}
55+
if (gcResource instanceof GcResourceSeries) {
56+
return loadModelFromSeries((GcResourceSeries) gcResource);
57+
}
5558
if (!(gcResource instanceof GcResourceFile))
5659
throw new UnsupportedOperationException("Only supported for files!");
5760

@@ -84,7 +87,7 @@ public GCModel loadModel(GCResource gcResource) throws DataReaderException {
8487
* @return a {@link GCModel} containing all events found in the given {@link GCResource}s that were readable
8588
* @throws DataReaderException
8689
*/
87-
public GCModel loadModelFromSeries(GcResourceSeries gcResource) throws DataReaderException {
90+
protected GCModel loadModelFromSeries(GcResourceSeries gcResource) throws DataReaderException {
8891
GcSeriesLoader seriesLoader = new GcSeriesLoader(this);
8992
return seriesLoader.load(gcResource);
9093
}

src/main/java/com/tagtraum/perf/gcviewer/model/GCModel.java

+20
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
import java.nio.file.Files;
1717
import java.nio.file.attribute.BasicFileAttributes;
1818
import java.time.Duration;
19+
import java.time.Instant;
20+
import java.time.ZoneId;
1921
import java.time.ZonedDateTime;
2022
import java.time.temporal.ChronoUnit;
2123
import java.util.*;
@@ -989,6 +991,24 @@ public Optional<Double> getFirstTimeStamp() {
989991
return Optional.empty();
990992
}
991993

994+
/**
995+
* Best effort calculation of this {@link GCModel}s start date based on the available information
996+
*
997+
* @return the most probable start date of this {@link GCModel}
998+
*/
999+
public ZonedDateTime getStartDate() {
1000+
ZonedDateTime suggestedStartDate = ZonedDateTime.ofInstant(Instant.ofEpochMilli(getLastModified()), ZoneId.systemDefault());
1001+
if (hasDateStamp()) {
1002+
suggestedStartDate = getFirstDateStamp();
1003+
}
1004+
else if (hasCorrectTimestamp()) {
1005+
double runningTimeInSeconds = getRunningTime();
1006+
long runningTimeInMillis = (long) (runningTimeInSeconds * 1000d);
1007+
suggestedStartDate = suggestedStartDate.minus(runningTimeInMillis, ChronoUnit.MILLIS);
1008+
}
1009+
return suggestedStartDate;
1010+
}
1011+
9921012
public String toString() {
9931013
return "GCModel[size=" + size() + "]: " + allEvents.toString();
9941014
}

src/main/java/com/tagtraum/perf/gcviewer/view/ModelChartImpl.java

+32-62
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
11
package com.tagtraum.perf.gcviewer.view;
22

3-
import java.awt.Color;
4-
import java.awt.Component;
5-
import java.awt.Dimension;
6-
import java.awt.Font;
7-
import java.awt.FontMetrics;
8-
import java.awt.Graphics;
9-
import java.awt.GridBagConstraints;
10-
import java.awt.GridBagLayout;
11-
import java.awt.Rectangle;
3+
import com.tagtraum.perf.gcviewer.model.GCModel;
4+
import com.tagtraum.perf.gcviewer.util.TimeFormat;
5+
import com.tagtraum.perf.gcviewer.view.model.GCPreferences;
6+
import com.tagtraum.perf.gcviewer.view.model.PropertyChangeEventConsts;
7+
import com.tagtraum.perf.gcviewer.view.renderer.*;
8+
9+
import javax.swing.*;
10+
import javax.swing.event.ChangeEvent;
11+
import javax.swing.event.ChangeListener;
12+
import javax.swing.event.SwingPropertyChangeSupport;
13+
import java.awt.*;
1214
import java.awt.event.ComponentEvent;
1315
import java.awt.event.ComponentListener;
1416
import java.awt.event.MouseAdapter;
@@ -18,36 +20,10 @@
1820
import java.text.DateFormat;
1921
import java.text.Format;
2022
import java.text.NumberFormat;
23+
import java.time.ZonedDateTime;
2124
import java.util.Date;
2225
import java.util.logging.Logger;
2326

24-
import javax.swing.JPanel;
25-
import javax.swing.JPopupMenu;
26-
import javax.swing.JScrollBar;
27-
import javax.swing.JScrollPane;
28-
import javax.swing.JViewport;
29-
import javax.swing.event.ChangeEvent;
30-
import javax.swing.event.ChangeListener;
31-
import javax.swing.event.SwingPropertyChangeSupport;
32-
33-
import com.tagtraum.perf.gcviewer.model.GCModel;
34-
import com.tagtraum.perf.gcviewer.util.TimeFormat;
35-
import com.tagtraum.perf.gcviewer.view.model.GCPreferences;
36-
import com.tagtraum.perf.gcviewer.view.model.PropertyChangeEventConsts;
37-
import com.tagtraum.perf.gcviewer.view.renderer.ConcurrentGcBegionEndRenderer;
38-
import com.tagtraum.perf.gcviewer.view.renderer.FullGCLineRenderer;
39-
import com.tagtraum.perf.gcviewer.view.renderer.GCRectanglesRenderer;
40-
import com.tagtraum.perf.gcviewer.view.renderer.GCTimesRenderer;
41-
import com.tagtraum.perf.gcviewer.view.renderer.IncLineRenderer;
42-
import com.tagtraum.perf.gcviewer.view.renderer.InitialMarkLevelRenderer;
43-
import com.tagtraum.perf.gcviewer.view.renderer.PolygonChartRenderer;
44-
import com.tagtraum.perf.gcviewer.view.renderer.TotalHeapRenderer;
45-
import com.tagtraum.perf.gcviewer.view.renderer.TotalTenuredRenderer;
46-
import com.tagtraum.perf.gcviewer.view.renderer.TotalYoungRenderer;
47-
import com.tagtraum.perf.gcviewer.view.renderer.UsedHeapRenderer;
48-
import com.tagtraum.perf.gcviewer.view.renderer.UsedTenuredRenderer;
49-
import com.tagtraum.perf.gcviewer.view.renderer.UsedYoungRenderer;
50-
5127
/**
5228
* Graphical chart of the gc file. It contains the chart and all rulers surrounding it but not
5329
* the model details on the right side.
@@ -59,7 +35,7 @@
5935
public class ModelChartImpl extends JScrollPane implements ModelChart, ChangeListener, PropertyChangeListener {
6036

6137
private static final Logger LOGGER = Logger.getLogger(ModelChartImpl.class.getName());
62-
38+
6339
private GCModel model;
6440
private Chart chart;
6541
private JScrollBar horizontalScrollBar;
@@ -182,7 +158,7 @@ public void componentHidden(ComponentEvent e) {}
182158
timeOffsetPanel = new TimeOffsetPanel(timestampRulerPopup);
183159
timestampRulerPopup.add(timeOffsetPanel);
184160
timeOffsetPanel.setCheckboxSelected(timestampRuler.getOffset() != 0);
185-
161+
186162
this.timestampRuler.addMouseListener(new MouseAdapter(){
187163
public void mousePressed(MouseEvent e) {
188164
maybePopup(e);
@@ -199,14 +175,8 @@ private void maybePopup(MouseEvent e) {
199175
timeOffsetPanel.setCheckboxSelected(true);
200176
}
201177
else {
202-
long suggestedStartDate = model.getLastModified();
203-
if (model.hasDateStamp()) {
204-
suggestedStartDate = model.getFirstDateStamp().toInstant().toEpochMilli();
205-
}
206-
else if (model.hasCorrectTimestamp()) {
207-
suggestedStartDate -= (long)(model.getRunningTime() * 1000.0d);
208-
}
209-
timeOffsetPanel.setDate(new Date(suggestedStartDate));
178+
ZonedDateTime suggestedStartDate = model.getStartDate();
179+
timeOffsetPanel.setDate(Date.from(suggestedStartDate.toInstant()));
210180
timeOffsetPanel.setCheckboxSelected(false);
211181
}
212182
timestampRulerPopup.show(e.getComponent(), e.getX(), e.getY());
@@ -219,16 +189,16 @@ else if (model.hasCorrectTimestamp()) {
219189

220190
public void addTimeOffsetChangeListener(PropertyChangeListener listener) {
221191
this.timeOffsetPanel.addPropertyChangeListener(
222-
PropertyChangeEventConsts.TIMEOFFSETPANEL_STATE_CHANGED,
192+
PropertyChangeEventConsts.TIMEOFFSETPANEL_STATE_CHANGED,
223193
listener);
224194
}
225-
195+
226196
public void removeTimeOffsetChangeListener(PropertyChangeListener listener) {
227197
this.timeOffsetPanel.removePropertyChangeListener(
228-
PropertyChangeEventConsts.TIMEOFFSETPANEL_STATE_CHANGED,
198+
PropertyChangeEventConsts.TIMEOFFSETPANEL_STATE_CHANGED,
229199
listener);
230200
}
231-
201+
232202
public void invalidate() {
233203
super.invalidate();
234204
chart.invalidate();
@@ -405,7 +375,7 @@ public void setShowDateStamp(boolean showDateStamp) {
405375
timestampRuler.revalidate();
406376
timestampRuler.repaint();
407377
}
408-
378+
409379
@Override
410380
public boolean isShowDateStamp(){
411381
return timestampRuler.getOffset() > 0;
@@ -541,7 +511,7 @@ private class Ruler extends JPanel {
541511
private String unitName;
542512
private int minHalfDistance;
543513
private double offset;
544-
514+
545515
private SwingPropertyChangeSupport propertyChangeSupport;
546516

547517
public Ruler(boolean vertical, double minUnit, double maxUnit, String unitName) {
@@ -555,18 +525,18 @@ public Ruler(boolean vertical, double minUnit, double maxUnit, String unitName,
555525
setMinUnit(minUnit);
556526
setMaxUnit(maxUnit);
557527
font = new Font("sans-serif", Font.PLAIN, 10);
558-
528+
559529
propertyChangeSupport = new SwingPropertyChangeSupport(this, true);
560530
}
561531

562532
public void addPropertyChangeListener(PropertyChangeListener listener) {
563533
this.propertyChangeSupport.addPropertyChangeListener(listener);
564534
}
565-
535+
566536
public void removePropertyChangeListener(PropertyChangeListener listener) {
567537
this.propertyChangeSupport.removePropertyChangeListener(listener);
568538
}
569-
539+
570540
public void setSize(int width, int height) {
571541
super.setSize(width, height);
572542
configureFormatter();
@@ -579,7 +549,7 @@ public Dimension getPreferredSize() {
579549
Dimension bestSize = null;
580550
if (isVertical()) {
581551
bestSize = new Dimension(minWidth, getHeight());
582-
}
552+
}
583553
else {
584554
bestSize = new Dimension((int) (runningTime * getScaleFactor()), fm.getHeight());
585555
minHalfDistance = minWidth;
@@ -691,7 +661,7 @@ private double getDateLineDistance() {
691661
double oneHourDistance = lineDistance;
692662
while (lineDistance < 20) lineDistance += oneHourDistance;
693663
}
694-
}
664+
}
695665
else {
696666
if (lineDistance < minHalfDistance * 2) lineDistance *= 10.0d; // 10sec
697667
if (lineDistance < minHalfDistance * 2) lineDistance *= 2.0d; // 20sec
@@ -715,15 +685,15 @@ private double getNumberLineDistance() {
715685
double lineDistance = getPixelsPerUnit() * Math.pow(10, Math.ceil(-log10PixelPerUnit) + 1);
716686
if (isVertical()) {
717687
while (lineDistance < 20) lineDistance *= 10.0d;
718-
}
688+
}
719689
else {
720690
while (lineDistance < minHalfDistance * 2) lineDistance *= 10.0d;
721691
}
722692
return lineDistance;
723693
}
724694

725695
private double getPixelsPerUnit() {
726-
return isVertical()
696+
return isVertical()
727697
? getHeight() / (maxUnit - minUnit)
728698
: (runningTime * getScaleFactor() / (maxUnit - minUnit));
729699
}
@@ -744,7 +714,7 @@ public void configureFormatter() {
744714
if (digits < 1) {
745715
((NumberFormat)formatter).setMaximumFractionDigits((int) Math.abs(digits) + 2);
746716
((NumberFormat)formatter).setMinimumFractionDigits((int) Math.abs(digits) + 2);
747-
}
717+
}
748718
else {
749719
((NumberFormat)formatter).setMaximumFractionDigits(0);
750720
((NumberFormat)formatter).setMinimumFractionDigits(0);
@@ -787,14 +757,14 @@ public void propertyChange(PropertyChangeEvent evt) {
787757
// and propagates the change outside firing its own event.
788758
// Like this it is possible for the menu and the other ModelChartImpls inside one
789759
// GCDocument to stay in sync.
790-
760+
791761
if (PropertyChangeEventConsts.RULER_OFFSET_CHANGED.equals(evt.getPropertyName())) {
792762
// dateStampShown is true, if some offset is present (0 offset = only time shown)
793763
boolean dateStampShown = ((Double)evt.getNewValue()).doubleValue() > 0.0001;
794764
firePropertyChange(
795765
PropertyChangeEventConsts.MODELCHART_TIMESTAMP_RULER_FORMAT_CHANGED,
796766
!dateStampShown,
797-
dateStampShown);
767+
dateStampShown);
798768
}
799769
}
800770

src/main/java/com/tagtraum/perf/gcviewer/view/model/GCResourceGroup.java

+16-3
Original file line numberDiff line numberDiff line change
@@ -138,8 +138,9 @@ public String getUrlGroupString() {
138138
}
139139

140140
/**
141-
* Get short version of resource names (only file name without path), if more than one
142-
* resource is in this group.
141+
* Get short version of resource names.<br>
142+
* If more than one resource is in this group, returns only file name without path.
143+
* {@link GcResourceSeries} are abbreviated by showing the name of the first file and how many files are following.
143144
*
144145
* @return get short group name (only file name without path), if there is more than one
145146
* resource
@@ -148,6 +149,7 @@ public String getGroupStringShort() {
148149
if (gcResourceList.size() > 1) {
149150
StringBuilder sb = new StringBuilder();
150151
for (String resourceName : gcResourceList) {
152+
resourceName = shortenGroupStringForSeries(resourceName);
151153
// test for "/" and "\\" because in Windows you have a "/" in a http url
152154
// but "\\" in file strings
153155
int lastIndexOfPathSeparator = resourceName.lastIndexOf("/");
@@ -159,10 +161,21 @@ public String getGroupStringShort() {
159161
return sb.toString();
160162
}
161163
else {
162-
return gcResourceList.get(0);
164+
String resourceName = gcResourceList.get(0);
165+
return shortenGroupStringForSeries(resourceName);
163166
}
164167
}
165168

169+
private String shortenGroupStringForSeries(String resourceName) {
170+
String[] splitBySeriesSeparator = resourceName.split(SERIES_SEPARATOR);
171+
if(splitBySeriesSeparator.length > 1)
172+
{
173+
// Series: Shorten description by showing first entry only + number of remaining files
174+
resourceName = splitBySeriesSeparator[0] + " (series, " + (splitBySeriesSeparator.length -1) +" more files)";
175+
}
176+
return resourceName;
177+
}
178+
166179
@Override
167180
public boolean equals(Object obj) {
168181
if (this == obj)

0 commit comments

Comments
 (0)