From 129f06c60cdac2c39ab8b5c9905e892093d9d2b9 Mon Sep 17 00:00:00 2001 From: Kirk Pepperdine Date: Tue, 28 Feb 2023 07:17:16 -0800 Subject: [PATCH] :bug: fix for issue #274 --- .../gctoolkit/io/GCLogFileSegment.java | 14 +-- .../gctoolkit/time/DateTimeStamp.java | 79 ++++----------- .../gctoolkit/time/DateTimeStampTest.java | 95 +++++++------------ .../gctoolkit/parser/ForwardReference.java | 1 + .../UnifiedGenerationalParserTest.java | 27 ++++++ 5 files changed, 83 insertions(+), 133 deletions(-) diff --git a/api/src/main/java/com/microsoft/gctoolkit/io/GCLogFileSegment.java b/api/src/main/java/com/microsoft/gctoolkit/io/GCLogFileSegment.java index e8f22661..b52f6cbb 100644 --- a/api/src/main/java/com/microsoft/gctoolkit/io/GCLogFileSegment.java +++ b/api/src/main/java/com/microsoft/gctoolkit/io/GCLogFileSegment.java @@ -72,12 +72,7 @@ public String getSegmentName() { public double getStartTime() { try { ageOfJVMAtLogStart(); - if ( startTime.hasTimeStamp()) - return startTime.getTimeStamp(); - else if ( startTime.hasDateStamp()) - return startTime.toEpochInMillis(); - else - return Double.MAX_VALUE; + return startTime.getTimeStamp(); } catch (NullPointerException ex) { return Double.MAX_VALUE; } @@ -96,12 +91,7 @@ else if ( startTime.hasDateStamp()) public double getEndTime() { try { ageOfJVMAtLogEnd(); - if ( endTime.hasTimeStamp()) - return endTime.getTimeStamp(); - else if ( endTime.hasDateStamp()) - return endTime.toEpochInMillis(); - else - return Double.MAX_VALUE; + return endTime.getTimeStamp(); } catch (NullPointerException|IOException ex) { return Double.MIN_VALUE; } diff --git a/api/src/main/java/com/microsoft/gctoolkit/time/DateTimeStamp.java b/api/src/main/java/com/microsoft/gctoolkit/time/DateTimeStamp.java index 8c0c9b86..af521d62 100644 --- a/api/src/main/java/com/microsoft/gctoolkit/time/DateTimeStamp.java +++ b/api/src/main/java/com/microsoft/gctoolkit/time/DateTimeStamp.java @@ -45,11 +45,9 @@ public class DateTimeStamp implements Comparable { private static final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZ"); private static ZonedDateTime dateFromString(String iso8601DateTime) { - if (iso8601DateTime != null) { - TemporalAccessor temporalAccessor = formatter.parse(iso8601DateTime); - return ZonedDateTime.from(temporalAccessor); - } - return null; + if ( iso8601DateTime == null) + return null; + return ZonedDateTime.from(formatter.parse(iso8601DateTime)); } private static double ageFromString(String doubleFormat) { @@ -151,6 +149,8 @@ public DateTimeStamp(ZonedDateTime dateTime, double timeStamp) { * @return The time stamp value, in decimal seconds. */ public double getTimeStamp() { + if (! hasTimeStamp()) + return toEpochInMillis(); return timeStamp; } @@ -179,14 +179,11 @@ public boolean hasTimeStamp() { public boolean equals(Object obj) { if (obj instanceof DateTimeStamp) { DateTimeStamp other = (DateTimeStamp) obj; - boolean hasTimeStamp = hasTimeStamp() && other.hasTimeStamp(); - boolean hasDateStamp = hasDateStamp() && other.hasDateStamp(); - if (hasDateStamp && hasTimeStamp) - return equals(other.getTimeStamp()) && getDateTime().equals(other.getDateTime()); - if (hasTimeStamp) - return equals(other.getTimeStamp()); - if (hasDateStamp) - return getDateTime().equals(other.getDateTime()); + if (this.hasDateStamp()) + return this.getDateTime().equals(other.getDateTime()) && + (this.getTimeStamp() == other.getTimeStamp()); + else + return getTimeStamp() == other.getTimeStamp(); } return false; } @@ -202,47 +199,17 @@ public String toString() { if (hasDateStamp()) buffer.append(getDateTime().toString()); if (hasTimeStamp()) - buffer.append("@").append(String.format(Locale.US,"%.3f",timeStamp)); + buffer.append("@").append(String.format(Locale.US,"%.3f",getTimeStamp())); return buffer.toString(); } - /** - * Return {@code true} if this time stamp is less than the other. - * @param other The other time stamp, in decimal seconds. - * @return {@code true} if this time stamp is less than the other. - */ - public boolean before(double other) { - if ( other < 0.000d || Double.isNaN(other)) return false; - if ( Double.isNaN(getTimeStamp())) return false; - return getTimeStamp() < other; - } - - /** - * Return {@code true} if this time stamp is greater than the other. - * @param other The other time stamp, in decimal seconds. - * @return {@code true} if this time stamp is greater than the other. - */ - public boolean after(double other) { - if ( other < 0.000d || Double.isNaN(other)) return false; - if ( Double.isNaN(getTimeStamp())) return false; - return getTimeStamp() > other; - } - - public boolean equals(double other) { - if ( other < 0.000d || Double.isNaN(other)) return false; - if ( Double.isNaN(getTimeStamp())) return false; - return getTimeStamp() == other; - } - /** * Return {@code true} if this DateTimeStamp comes before the other. * @param other The other DateTimeStamp. * @return {@code true} if this time stamp is less than the other. */ public boolean before(DateTimeStamp other) { - return ( hasTimeStamp() && other.hasTimeStamp()) - ? before(other.getTimeStamp()) - : compare(other.getDateTime()) < 0; + return getTimeStamp() < other.getTimeStamp(); } /** @@ -251,9 +218,7 @@ public boolean before(DateTimeStamp other) { * @return {@code true} if this time stamp is less than the other. */ public boolean after(DateTimeStamp other) { - return ( hasTimeStamp() && other.hasTimeStamp()) - ? after(other.getTimeStamp()) - : compare(other.getDateTime()) > 0; + return getTimeStamp() > other.getTimeStamp(); } /** @@ -284,26 +249,20 @@ public DateTimeStamp add(double offsetInDecimalSeconds) { if (Double.isNaN(offsetInDecimalSeconds)) throw new IllegalArgumentException("Cannot add " + Double.NaN); - DateTimeStamp now; double adjustedTimeStamp = Double.NaN; - if ( ! Double.isNaN(getTimeStamp())) { + ZonedDateTime adjustedDateStamp = null; + if ( hasTimeStamp()) { adjustedTimeStamp = getTimeStamp() + offsetInDecimalSeconds; } - // Need to scale the values from ZonedDateTime - if (getDateTime() != null) { + if (hasDateStamp()) { double offset = (Double.isNaN(offsetInDecimalSeconds)) ? 0.000d : offsetInDecimalSeconds; int seconds = (int) offset; long nanos = ((long) ((offset % 1) * 1_000L)) * 1_000_000L; - ZonedDateTime adjustedDateStamp = dateTime.plusSeconds(seconds).plusNanos(nanos); - if ( Double.isNaN(getTimeStamp())) - now = new DateTimeStamp(adjustedDateStamp); - else - now = new DateTimeStamp(adjustedDateStamp, adjustedTimeStamp); - } else - now = new DateTimeStamp(adjustedTimeStamp); + adjustedDateStamp = dateTime.plusSeconds(seconds).plusNanos(nanos); + } - return now; + return new DateTimeStamp(adjustedDateStamp,adjustedTimeStamp); } /** diff --git a/api/src/test/java/com/microsoft/gctoolkit/time/DateTimeStampTest.java b/api/src/test/java/com/microsoft/gctoolkit/time/DateTimeStampTest.java index ce1d45d8..8df4ec58 100644 --- a/api/src/test/java/com/microsoft/gctoolkit/time/DateTimeStampTest.java +++ b/api/src/test/java/com/microsoft/gctoolkit/time/DateTimeStampTest.java @@ -15,19 +15,19 @@ public class DateTimeStampTest { private static final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZ"); @Test - public void getTimeStamp() { + void getTimeStamp() { DateTimeStamp dateTimeStamp = new DateTimeStamp(.586); assertEquals(.586, dateTimeStamp.getTimeStamp(), 0.0001); dateTimeStamp = new DateTimeStamp("2018-04-04T09:10:00.586-0100"); - assertEquals(Double.NaN, dateTimeStamp.getTimeStamp(), 0.0001); + assertEquals(1.522836600586E12, dateTimeStamp.getTimeStamp(), 0.0001); dateTimeStamp = new DateTimeStamp("2018-04-04T09:10:00.586-0100", 0.18); assertEquals(.18, dateTimeStamp.getTimeStamp(), 0.0001); } @Test - public void getDateStampAsString() { + void getDateStampAsString() { DateTimeStamp dateTimeStamp = new DateTimeStamp(.586); assertEquals("@0.586", dateTimeStamp.toString()); @@ -39,7 +39,7 @@ public void getDateStampAsString() { } @Test - public void getDateTime() { + void getDateTime() { DateTimeStamp dateTimeStamp = new DateTimeStamp(.586); assertNull(dateTimeStamp.getDateTime()); @@ -51,7 +51,7 @@ public void getDateTime() { } @Test - public void hasDateStamp() { + void hasDateStamp() { DateTimeStamp dateTimeStamp = new DateTimeStamp(.586); assertFalse(dateTimeStamp.hasDateStamp()); @@ -63,7 +63,7 @@ public void hasDateStamp() { } @Test - public void testHash() { + void testHash() { DateTimeStamp a = new DateTimeStamp(.586); DateTimeStamp b = new DateTimeStamp(.587); assertNotEquals(a.hashCode(), b.hashCode()); @@ -99,9 +99,9 @@ public void testHash() { } @Test - public void testEquals() { - DateTimeStamp a = new DateTimeStamp(.586); - DateTimeStamp b = new DateTimeStamp(.586); + void testEquals() { + DateTimeStamp a = new DateTimeStamp(0.586d); + DateTimeStamp b = new DateTimeStamp(0.586d); assertEquals(a,b); assertEquals(b,a); b = new DateTimeStamp(.587); @@ -135,7 +135,7 @@ public void testEquals() { } @Test - public void testBefore() { + void testBefore() { DateTimeStamp a; DateTimeStamp b; @@ -175,7 +175,7 @@ public void testBefore() { } @Test - public void testAfter() { + void testAfter() { DateTimeStamp a; DateTimeStamp b; @@ -215,7 +215,7 @@ public void testAfter() { } @Test - public void compare() { + void compare() { DateTimeStamp a = new DateTimeStamp("2018-04-04T09:10:00.586-0100"); DateTimeStamp b = new DateTimeStamp("2018-04-04T09:10:00.587-0100"); assertTrue(a.compare(b.getDateTime()) < 0); @@ -236,7 +236,7 @@ public void compare() { } @Test - public void add() { + void add() { DateTimeStamp a = new DateTimeStamp(.586); double a_ts = a.getTimeStamp(); ZonedDateTime a_dt = a.getDateTime(); @@ -266,7 +266,7 @@ public void add() { } @Test - public void minus() { + void minus() { DateTimeStamp a = new DateTimeStamp(.586); double a_ts = a.getTimeStamp(); ZonedDateTime a_dt = a.getDateTime(); @@ -296,7 +296,7 @@ public void minus() { } @Test - public void testMinus() { + void testMinus() { DateTimeStamp a = new DateTimeStamp(.586); DateTimeStamp b = new DateTimeStamp(.587); double diff = a.minus(b); @@ -316,7 +316,7 @@ public void testMinus() { } @Test - public void timeSpanInMinutes() { + void timeSpanInMinutes() { DateTimeStamp a = new DateTimeStamp(.586); DateTimeStamp b = new DateTimeStamp(.587); double diff = b.timeSpanInMinutes(a); @@ -334,134 +334,107 @@ public void timeSpanInMinutes() { } @Test - public void testCompareLessThan() { + void testCompareLessThan() { DateTimeStamp smaller = new DateTimeStamp("2018-04-04T09:10:00.586-0100"); DateTimeStamp greater = new DateTimeStamp("2018-04-04T10:10:00.587-0100"); assertEquals(-1, smaller.compareTo(greater)); } @Test - public void testCompareGreaterThan() { + void testCompareGreaterThan() { DateTimeStamp smaller = new DateTimeStamp("2018-04-04T09:10:00.586-0100"); DateTimeStamp greater = new DateTimeStamp("2018-04-04T10:10:00.587-0100"); assertEquals(1, greater.compareTo(smaller)); } @Test - public void testCompareEquals() { + void testCompareEquals() { DateTimeStamp object1 = new DateTimeStamp("2018-04-04T10:10:00.586-0100"); DateTimeStamp object2 = new DateTimeStamp("2018-04-04T10:10:00.586-0100"); assertEquals(0, object1.compareTo(object2)); } @Test - public void testCompareEqualsTimeStamp() { + void testCompareEqualsTimeStamp() { DateTimeStamp object1 = new DateTimeStamp("2018-04-04T10:10:00.586-0100", 123); DateTimeStamp object2 = new DateTimeStamp("2018-04-04T10:10:00.586-0100", 123); assertEquals(0, object2.compareTo(object1)); } @Test - public void testCompareGreaterTimeStamp() { + void testCompareGreaterTimeStamp() { DateTimeStamp smaller = new DateTimeStamp("2018-04-04T10:10:00.586-0100", 122); DateTimeStamp greater = new DateTimeStamp("2018-04-04T10:10:00.586-0100", 123); assertEquals(1, greater.compareTo(smaller)); } @Test - public void testCompareSmallerTimeStamp() { + void testCompareSmallerTimeStamp() { DateTimeStamp smaller = new DateTimeStamp("2018-04-04T10:10:00.586-0100", 123); DateTimeStamp greater = new DateTimeStamp("2018-04-04T10:10:00.586-0100", 124); assertEquals(-1, smaller.compareTo(greater)); } @Test - public void testCompareNullValue() { + void testCompareNullValue() { DateTimeStamp smaller = new DateTimeStamp("2018-04-04T09:10:00.586-0100"); assertEquals(-1, smaller.compareTo(null)); } @Test - public void testCompareEqualsTimeStampWithoutDateTime() { + void testCompareEqualsTimeStampWithoutDateTime() { DateTimeStamp object1 = new DateTimeStamp(123); DateTimeStamp object2 = new DateTimeStamp(123); assertEquals(0, object2.compareTo(object1)); } @Test - public void testCompareGreaterTimeStampWithoutDateTime() { + void testCompareGreaterTimeStampWithoutDateTime() { DateTimeStamp smaller = new DateTimeStamp(122); DateTimeStamp greater = new DateTimeStamp(124); assertEquals(1, greater.compareTo(smaller)); } @Test - public void testCompareSmallerTimeStampWithoutDateTime() { + void testCompareSmallerTimeStampWithoutDateTime() { DateTimeStamp smaller = new DateTimeStamp(123); DateTimeStamp greater = new DateTimeStamp(124); assertEquals(-1, smaller.compareTo(greater)); } - /** - * This tests a case that can't happen in context of a GC log. - */ - @Test - public void testCompareSmallerTimeStampMixed() { - DateTimeStamp smaller = new DateTimeStamp(123); - DateTimeStamp greater = new DateTimeStamp("2018-04-04T10:10:00.586-0100"); - assertThrows(IllegalStateException.class, - () -> { smaller.compareTo(greater); }, - "IllegalStateException Not Thrown"); - } - @Test - public void testAddingNaN() { + void testAddingNaN() { assertThrows(IllegalArgumentException.class, () -> { new DateTimeStamp("2018-04-04T10:10:00.586-0100").add(Double.NaN); }, "IllegalAccess Not Thrown"); } @Test - public void testNanWithMinusNonZero() { + void testNanWithMinusNonZero() { assertThrows(IllegalArgumentException.class, () -> { new DateTimeStamp("2018-04-04T10:10:00.586-0100").minus(Double.NaN); }, "IllegalAccess Not Thrown"); } @Test - public void testNanWithMinus() { + void testNanWithMinus() { DateTimeStamp dateTimeStamp = new DateTimeStamp("2018-04-04T10:09:59.586-0100"); DateTimeStamp forComparing = new DateTimeStamp("2018-04-04T10:10:00.586-0100").minus(1.0d); assertEquals(dateTimeStamp, forComparing); } @Test - public void testNanWithConstructor() { + void testNanWithConstructor() { DateTimeStamp dateTimeStamp = new DateTimeStamp((String) null,Double.NaN); DateTimeStamp forComparing = new DateTimeStamp(0.0); assertNotEquals(dateTimeStamp, forComparing); } - // Maybe every time should be after NaN, but it's NaN so IllegalStateException? Is this a use case in the context of a GC log - @Test - public void testBeforeForNAN(){ - DateTimeStamp dateTimeStamp = new DateTimeStamp(-1); - boolean before = dateTimeStamp.before(Double.NaN); - assertFalse(before); - } - - @Test - public void testAfterForNAN(){ - DateTimeStamp dateTimeStamp = new DateTimeStamp(1); - boolean after = dateTimeStamp.after(Double.NaN); - assertFalse(after); - } - /* * */ @Test - public void compareWithNANValue(){ + void compareWithNANValue(){ // This is an illegal state which is unlikely to happen in the context of a single GC log. DateTimeStamp dateTimeStamp = new DateTimeStamp(12d); DateTimeStamp dateTimeStampCompare = new DateTimeStamp(Double.NaN); @@ -472,7 +445,7 @@ public void compareWithNANValue(){ @Test - public void compareWithNullDates() { + void compareWithNullDates() { DateTimeStamp stamp1 = new DateTimeStamp((String)null, 100); DateTimeStamp stamp2 = new DateTimeStamp((String)null, 200); DateTimeStamp stamp3 = new DateTimeStamp((String)null, 100); @@ -482,7 +455,7 @@ public void compareWithNullDates() { } @Test - public void compareToTransitivity() { + void compareToTransitivity() { DateTimeStamp stamp1 = new DateTimeStamp("2021-09-01T11:12:13.111-0100", 100); DateTimeStamp stamp2 = new DateTimeStamp((String)null, 200); DateTimeStamp stamp3 = new DateTimeStamp("2021-08-31T11:12:13.111-0100", 300); @@ -493,7 +466,7 @@ public void compareToTransitivity() { } @Test - public void compareToTransitivityWithEqualTimeStamps() { + void compareToTransitivityWithEqualTimeStamps() { DateTimeStamp stamp1 = new DateTimeStamp("2021-09-01T11:12:13.111-0100", 100); DateTimeStamp stamp2 = new DateTimeStamp((String)null, 100); DateTimeStamp stamp3 = new DateTimeStamp("2021-08-31T11:12:13.111-0100", 100); diff --git a/parser/src/main/java/com/microsoft/gctoolkit/parser/ForwardReference.java b/parser/src/main/java/com/microsoft/gctoolkit/parser/ForwardReference.java index 91899eab..27077bb9 100644 --- a/parser/src/main/java/com/microsoft/gctoolkit/parser/ForwardReference.java +++ b/parser/src/main/java/com/microsoft/gctoolkit/parser/ForwardReference.java @@ -19,6 +19,7 @@ public class ForwardReference { ForwardReference(Decorators decorators, int id) { this.gcID = id; this.decorators = decorators; + this.startTime = decorators.getDateTimeStamp(); } int getGcID() { diff --git a/parser/src/test/java/com/microsoft/gctoolkit/parser/unittests/UnifiedGenerationalParserTest.java b/parser/src/test/java/com/microsoft/gctoolkit/parser/unittests/UnifiedGenerationalParserTest.java index f762bfd4..0ef4e355 100644 --- a/parser/src/test/java/com/microsoft/gctoolkit/parser/unittests/UnifiedGenerationalParserTest.java +++ b/parser/src/test/java/com/microsoft/gctoolkit/parser/unittests/UnifiedGenerationalParserTest.java @@ -38,4 +38,31 @@ public void testForDetailsLogs() { // 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 { 0, 0, 0, 0, 0, 0, 0, 4638, 28, 0, 0, 0, 0}, }; + + @Test + public void testCMSLogs() { + int i = 0; + for (String name : cms) { + try { + Path path = new TestLogFile("cms/" + name).getFile().toPath(); + TestResults testResults = testGenerationalSingleLogFile(path); + analyzeResults(name, testResults, cmsNumberOfDifferentCollectors[i], cmsCounts[i++]); + } catch (IOException ioe) { + fail(ioe.getMessage()); + } + } + } + + private static final String[] cms = { + "no_timestamps.log" + }; + + private static final int[] cmsNumberOfDifferentCollectors = { + 4, + }; + + private static final int[][] cmsCounts = { + // 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 + { 0, 0, 4461, 0, 0, 2, 0, 0, 0, 0, 0, 2, 2}, + }; }