Skip to content
Permalink
Browse files

6936: Parser should track statistics during parsing

Reviewed-by: hirt
  • Loading branch information
jpbempel authored and thegreystone committed Mar 2, 2021
1 parent e52a361 commit 0c7ae2a0f6423d76f74d9dba53fe5d693a3a7c0c
Showing with 562 additions and 63 deletions.
  1. +44 −4 .../org.openjdk.jmc.flightrecorder/src/main/java/org/openjdk/jmc/flightrecorder/EventCollection.java
  2. +61 −0 core/org.openjdk.jmc.flightrecorder/src/main/java/org/openjdk/jmc/flightrecorder/IParserStats.java
  3. +48 −1 ...org.openjdk.jmc.flightrecorder/src/main/java/org/openjdk/jmc/flightrecorder/RecordingPrinter.java
  4. +40 −1 ...openjdk.jmc.flightrecorder/src/main/java/org/openjdk/jmc/flightrecorder/internal/EventArrays.java
  5. +2 −1 ...c.flightrecorder/src/main/java/org/openjdk/jmc/flightrecorder/internal/FlightRecordingLoader.java
  6. +23 −2 ...mc.flightrecorder/src/main/java/org/openjdk/jmc/flightrecorder/internal/parser/LoaderContext.java
  7. +150 −0 ....jmc.flightrecorder/src/main/java/org/openjdk/jmc/flightrecorder/internal/parser/ParserStats.java
  8. +2 −1 ...flightrecorder/src/main/java/org/openjdk/jmc/flightrecorder/internal/parser/v0/ChunkLoaderV0.java
  9. +11 −5 ...trecorder/src/main/java/org/openjdk/jmc/flightrecorder/internal/parser/v0/EventParserManager.java
  10. +4 −3 ...flightrecorder/src/main/java/org/openjdk/jmc/flightrecorder/internal/parser/v1/ChunkLoaderV1.java
  11. +14 −1 ...c.flightrecorder/src/main/java/org/openjdk/jmc/flightrecorder/internal/parser/v1/TypeManager.java
  12. +2 −2 ...penjdk/jmc/flightrecorder/parser/synthetic/{JdkTypeIDsPreJdk11.java → OracleJdkTypeIDsPre11.java}
  13. +39 −38 ...htrecorder/src/main/java/org/openjdk/jmc/flightrecorder/parser/synthetic/SettingsTransformer.java
  14. +2 −2 ...er/src/main/java/org/openjdk/jmc/flightrecorder/parser/synthetic/SyntheticAttributeExtension.java
  15. +34 −1 ...njdk.jmc.flightrecorder.test/src/test/java/org/openjdk/jmc/flightrecorder/test/RecordingTest.java
  16. +15 −1 ....flightrecorder.test/src/test/java/org/openjdk/jmc/flightrecorder/test/util/RecordingToolkit.java
  17. +8 −0 core/tests/org.openjdk.jmc.flightrecorder.test/src/test/resources/stats/7u40.txt
  18. +8 −0 core/tests/org.openjdk.jmc.flightrecorder.test/src/test/resources/stats/7u60.txt
  19. +8 −0 core/tests/org.openjdk.jmc.flightrecorder.test/src/test/resources/stats/7u76.txt
  20. +7 −0 core/tests/org.openjdk.jmc.flightrecorder.test/src/test/resources/stats/8u0.txt
  21. +9 −0 core/tests/org.openjdk.jmc.flightrecorder.test/src/test/resources/stats/8u20.txt
  22. +12 −0 core/tests/org.openjdk.jmc.flightrecorder.test/src/test/resources/stats/8u40.txt
  23. +9 −0 core/tests/org.openjdk.jmc.flightrecorder.test/src/test/resources/stats/8u60.txt
  24. +10 −0 core/tests/org.openjdk.jmc.flightrecorder.test/src/test/resources/stats/9u0.txt
@@ -38,6 +38,7 @@
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.util.function.Consumer;
import java.util.function.Predicate;

import org.openjdk.jmc.common.collection.IteratorToolkit;
@@ -53,11 +54,12 @@
import org.openjdk.jmc.common.util.PredicateToolkit;
import org.openjdk.jmc.flightrecorder.internal.EventArray;
import org.openjdk.jmc.flightrecorder.internal.EventArrays;
import org.openjdk.jmc.flightrecorder.internal.parser.ParserStats;

/**
* Implementation of {@link IItemCollection} using {@link IItemIterable} iterators.
*/
class EventCollection implements IItemCollection {
class EventCollection implements IItemCollection, IParserStats {

private static class EventTypeEntry implements IItemIterable {

@@ -114,19 +116,22 @@ public EventTypeEntry apply(Predicate<IItem> filter) {
private final Set<IType<IItem>> types = new HashSet<>();
private final ArrayList<EventTypeEntry> items;
private final Set<IRange<IQuantity>> chunkRanges;
private final ParserStats parserStats;

static IItemCollection build(EventArrays events) {
ArrayList<EventTypeEntry> items = new ArrayList<>(events.getArrays().length);
for (EventArray ea : events.getArrays()) {
EventTypeEntry entry = new EventTypeEntry(ea);
items.add(entry);
}
return new EventCollection(items, events.getChunkTimeranges());
return new EventCollection(items, events.getChunkTimeranges(), events.getParserStats());
}

private EventCollection(ArrayList<EventTypeEntry> items, Set<IRange<IQuantity>> chunkRanges) {
private EventCollection(ArrayList<EventTypeEntry> items, Set<IRange<IQuantity>> chunkRanges,
ParserStats parserStats) {
this.items = items;
this.chunkRanges = chunkRanges;
this.parserStats = parserStats;
for (EventTypeEntry e : items) {
types.add(e.events.getType());
}
@@ -143,7 +148,7 @@ public EventCollection apply(IItemFilter filter) {
newEntries.add(newEntry);
}
}
return new EventCollection(newEntries, chunkRanges);
return new EventCollection(newEntries, chunkRanges, parserStats);
}

private static Iterator<IItem> buildIterator(IItem[] array, Predicate<? super IItem> filter) {
@@ -222,4 +227,39 @@ public void remove() {
public Set<IRange<IQuantity>> getUnfilteredTimeRanges() {
return chunkRanges;
}

@Override
public void forEachEventType(Consumer<IEventStats> consumer) {
parserStats.forEachEventType(consumer);
}

@Override
public short getMajorVersion() {
return parserStats.getMajorVersion();
}

@Override
public short getMinorVersion() {
return parserStats.getMinorVersion();
}

@Override
public int getChunkCount() {
return parserStats.getChunkCount();
}

@Override
public long getSkippedEventCount() {
return parserStats.getSkippedEventCount();
}

@Override
public long getEventCountByType(String eventTypeName) {
return parserStats.getCount(eventTypeName);
}

@Override
public long getEventTotalSizeByType(String eventTypeName) {
return parserStats.getTotalSize(eventTypeName);
}
}
@@ -0,0 +1,61 @@
/*
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2021, Datadog, Inc. All rights reserved.
*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* The contents of this file are subject to the terms of either the Universal Permissive License
* v 1.0 as shown at http://oss.oracle.com/licenses/upl
*
* or the following license:
*
* Redistribution and use in source and binary forms, with or without modification, are permitted
* provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions
* and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of
* conditions and the following disclaimer in the documentation and/or other materials provided with
* the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors may be used to
* endorse or promote products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
* WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.openjdk.jmc.flightrecorder;

import java.util.function.Consumer;

public interface IParserStats {

public interface IEventStats {
String getName();

long getCount();

long getTotalSize();
}

void forEachEventType(Consumer<IEventStats> consumer);

short getMajorVersion();

short getMinorVersion();

int getChunkCount();

long getSkippedEventCount();

long getEventCountByType(String eventTypeName);

long getEventTotalSizeByType(String eventTypeName);
}
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved.
*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@@ -41,6 +41,8 @@
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
import java.util.Map.Entry;

import org.openjdk.jmc.common.IDescribable;
@@ -59,6 +61,7 @@
import org.openjdk.jmc.common.item.ItemToolkit;
import org.openjdk.jmc.common.unit.IQuantity;
import org.openjdk.jmc.common.util.FormatToolkit;
import org.openjdk.jmc.flightrecorder.IParserStats.IEventStats;
import org.openjdk.jmc.flightrecorder.parser.IParserExtension;
import org.openjdk.jmc.flightrecorder.parser.ParserExtensionRegistry;
import org.openjdk.jmc.flightrecorder.parser.filter.FilterExtension;
@@ -88,6 +91,11 @@
* Only write one line per event
*/
LOW,

/**
* Write only a summary of the recording
*/
SUMMARY,
}

private final Verbosity verbosity;
@@ -141,6 +149,10 @@ public static void main(String[] args) throws IOException, InterruptedException,
}

public void print(IItemCollection events) {
if (verbosity == Verbosity.SUMMARY) {
printSummary((IParserStats) events);
return;
}
out.println("<?xml version=\"1.0\"?>"); //$NON-NLS-1$
Iterator<IItemIterable> itemIterable = events.iterator();
while (itemIterable.hasNext()) {
@@ -153,6 +165,39 @@ public void print(IItemCollection events) {
out.flush();
}

private void printSummary(IParserStats parserStats) {
out.printf("Version: %d.%d\n", parserStats.getMajorVersion(), parserStats.getMinorVersion());
out.printf("Chunks: %d\n", parserStats.getChunkCount());
// Order descending by event count
Set<IEventStats> eventStatsSet = new TreeSet<>((o1, o2) -> Long.compare(o2.getCount(), o1.getCount()));
parserStats.forEachEventType((eventStats) -> {
eventStatsSet.add(eventStats);
});
int minWidth = 0;
for (IEventStats eventStats : eventStatsSet) {
minWidth = Math.max(minWidth, eventStats.getName().length());
}
out.println();
String header = " Count Size (bytes) ";
String typeHeader = " Event Type";
minWidth = Math.max(minWidth, typeHeader.length());
out.println(typeHeader + pad(minWidth - typeHeader.length(), ' ') + header);
out.println(pad(minWidth + header.length(), '='));
for (IEventStats eventStats : eventStatsSet) {
out.printf(" %-" + minWidth + "s%10d %12d\n", eventStats.getName(), eventStats.getCount(),
eventStats.getTotalSize());
}
out.flush();
}

private String pad(int count, char c) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < count; i++) {
sb.append(c);
}
return sb.toString();
}

private static RecordingPrinter buildFromOptions(PrintWriter output, String[] args) throws ParseException {
Verbosity verbosity = Verbosity.HIGH;
IOnLoadFilter recordingFilter = null;
@@ -164,6 +209,8 @@ private static RecordingPrinter buildFromOptions(PrintWriter output, String[] ar
verbosity = Verbosity.LOW;
} else if (args[n].equals("-includeevents")) { //$NON-NLS-1$
recordingFilter = OnLoadFilters.includeEvents(Arrays.asList(args[++n].split(","))); //$NON-NLS-1$
} else if (args[n].equals("-summary")) {
verbosity = Verbosity.SUMMARY;
} else {
throw new ParseException("Unknown command " + args[n], n); //$NON-NLS-1$
}
@@ -1,18 +1,53 @@
/*
* Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved.
*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* The contents of this file are subject to the terms of either the Universal Permissive License
* v 1.0 as shown at http://oss.oracle.com/licenses/upl
*
* or the following license:
*
* Redistribution and use in source and binary forms, with or without modification, are permitted
* provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions
* and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of
* conditions and the following disclaimer in the documentation and/or other materials provided with
* the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors may be used to
* endorse or promote products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
* WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.openjdk.jmc.flightrecorder.internal;

import java.util.Set;

import org.openjdk.jmc.common.unit.IQuantity;
import org.openjdk.jmc.common.unit.IRange;
import org.openjdk.jmc.flightrecorder.internal.parser.ParserStats;

public class EventArrays {

private final EventArray[] arrays;
private final Set<IRange<IQuantity>> chunkTimeranges;
private final ParserStats parserStats;

public EventArrays(EventArray[] arrays, Set<IRange<IQuantity>> ranges) {
public EventArrays(EventArray[] arrays, Set<IRange<IQuantity>> ranges, ParserStats parserStats) {
this.arrays = arrays;
this.chunkTimeranges = ranges;
this.parserStats = parserStats;
}

public EventArray[] getArrays() {
@@ -23,4 +58,8 @@ public EventArrays(EventArray[] arrays, Set<IRange<IQuantity>> ranges) {
return chunkTimeranges;
}

public ParserStats getParserStats() {
return parserStats;
}

}
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved.
*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@@ -294,6 +294,7 @@ private static IChunkLoader createChunkLoader(
try {
Chunk chunk = chunkSupplier.getNextChunk(buffer);
if (chunk != null) {
context.setVersion(chunk.getMajorVersion(), chunk.getMinorVersion());
switch (chunk.getMajorVersion()) {
case VERSION_0:
return ChunkLoaderV0.create(chunk, context);
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved.
*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@@ -37,6 +37,7 @@
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

@@ -64,6 +65,7 @@
private final boolean hideExperimentals;
private final List<? extends IParserExtension> extensions;
private final Set<IRange<IQuantity>> chunkRanges;
private final ParserStats parserStats = new ParserStats();

public LoaderContext(List<? extends IParserExtension> extensions, boolean hideExperimentals) {
this.extensions = extensions;
@@ -134,7 +136,26 @@ public EventArrays buildEventArrays() throws CouldNotLoadRecordingException {
}

}
return new EventArrays(eventArrays.toArray(new EventArray[eventArrays.size()]), chunkRanges);
return new EventArrays(eventArrays.toArray(new EventArray[eventArrays.size()]), chunkRanges, parserStats);
}

public void incChunkCount() {
parserStats.incChunkCount();
}

public void updateEventStats(String eventTypeName, long size) {
parserStats.updateEventStats(eventTypeName, size);
}

public ParserStats getParserStats() {
return parserStats;
}

public void setVersion(short majorVersion, short minorVersion) {
parserStats.setVersion(majorVersion, minorVersion);
}

public void setSkippedEventCount(long skippedEventCount) {
parserStats.setSkippedEventCount(skippedEventCount);
}
}

0 comments on commit 0c7ae2a

Please sign in to comment.