--- a/src/jdk.jfr/share/classes/jdk/jfr/consumer/ChunkParser.java Fri May 24 20:51:28 2019 +0200
+++ b/src/jdk.jfr/share/classes/jdk/jfr/consumer/ChunkParser.java Mon May 27 18:33:13 2019 +0200
@@ -61,9 +61,15 @@
private LongMap<Parser> parsers;
private boolean chunkFinished;
private InternalEventFilter eventFilter = InternalEventFilter.ACCEPT_ALL;
+ private boolean reuse;
- public ChunkParser(RecordingInput input) throws IOException {
+ public ChunkParser(RecordingInput input, boolean reuse) throws IOException {
this(new ChunkHeader(input), null, 500);
+ this.reuse = reuse;
+ }
+
+ public void setReuse(boolean resue) {
+ this.reuse = resue;
}
private ChunkParser(ChunkHeader header, ChunkParser previous, long pollInterval) throws IOException {
@@ -108,10 +114,13 @@
return this.eventFilter;
}
- private void updateParserFilters() {
+ private void updateParsers() {
parsers.forEach(p -> {
if (p instanceof EventParser) {
EventParser ep = (EventParser) p;
+ if (reuse) {
+ ep.setReuse(true);
+ }
long threshold = eventFilter.getThreshold(ep.getEventType().getName());
if (threshold >= 0) {
ep.setEnabled(true);
@@ -152,7 +161,7 @@
ParserFactory factory = new ParserFactory(metadata, constantLookups, timeConverter);
parsers = factory.getParsers();
typeMap = factory.getTypeMap();
- updateParserFilters();
+ updateParsers();
}
if (contantPosition != chunkHeader.getConstantPoolPosition()) {
Logger.log(LogTag.JFR_SYSTEM_PARSER, LogLevel.INFO, "Found new constant pool data. Filling up pools with new values");
--- a/src/jdk.jfr/share/classes/jdk/jfr/consumer/EventDirectoryStream.java Fri May 24 20:51:28 2019 +0200
+++ b/src/jdk.jfr/share/classes/jdk/jfr/consumer/EventDirectoryStream.java Mon May 27 18:33:13 2019 +0200
@@ -102,6 +102,10 @@
}
runCloseActions();
}
+
+ public void setReuse(boolean reuse) {
+ // ignore hint
+ }
}
private final EventSetConsumer eventConsumer;
@@ -172,4 +176,9 @@
public void awaitTermination() {
eventConsumer.awaitTermination(Duration.ofMillis(0));
}
+
+ @Override
+ public void setReuse(boolean reuse) {
+ eventConsumer.setReuse(reuse);
+ }
}
--- a/src/jdk.jfr/share/classes/jdk/jfr/consumer/EventFileStream.java Fri May 24 20:51:28 2019 +0200
+++ b/src/jdk.jfr/share/classes/jdk/jfr/consumer/EventFileStream.java Mon May 27 18:33:13 2019 +0200
@@ -45,8 +45,7 @@
private final static class FileEventConsumer extends EventConsumer {
private final RecordingInput input;
private ChunkParser chunkParser;
- private RecordedEvent event;
- private boolean moreEvents = true;
+ private boolean reuse = true;
public FileEventConsumer(AccessControlContext acc, RecordingInput input) throws IOException {
super(acc);
@@ -55,12 +54,14 @@
@Override
public void process() throws Exception {
- chunkParser = new ChunkParser(input);
- while (moreEvents) {
+ chunkParser = new ChunkParser(input, reuse);
+ chunkParser.setReuse(reuse);
+ RecordedEvent event;
+ while (true) {
event = chunkParser.readEvent();
if (event == null) {
- findNext();
- if (!moreEvents) {
+ event = findNext();
+ if (event == null) {
return;
}
}
@@ -68,18 +69,24 @@
}
}
- private void findNext() throws IOException {
+ private RecordedEvent findNext() throws IOException {
+ RecordedEvent event = null;
while (event == null) {
- if (chunkParser == null) {
- chunkParser = new ChunkParser(input);
- } else if (!chunkParser.isLastChunk()) {
- chunkParser = chunkParser.nextChunkParser();
- } else {
- moreEvents = false;
- return;
+ if (chunkParser.isLastChunk()) {
+ return null;
}
+ chunkParser = chunkParser.nextChunkParser();
event = chunkParser.readEvent();
}
+ return event;
+ }
+
+ public void setReuse(boolean reuse) {
+ if (chunkParser == null) {
+ this.reuse = reuse;
+ } else {
+ chunkParser.setReuse(reuse);
+ }
}
}
@@ -139,6 +146,10 @@
eventConsumer.start(0);
}
+ public void setReuse(boolean reuse) {
+ eventConsumer.setReuse(reuse);
+ }
+
@Override
public void startAsync() {
eventConsumer.startAsync(0);
--- a/src/jdk.jfr/share/classes/jdk/jfr/consumer/EventParser.java Fri May 24 20:51:28 2019 +0200
+++ b/src/jdk.jfr/share/classes/jdk/jfr/consumer/EventParser.java Mon May 27 18:33:13 2019 +0200
@@ -46,8 +46,10 @@
private final boolean hasDuration;
private final List<ValueDescriptor> valueDescriptors;
private final int startIndex;
+ private final RecordedEvent event;
private long thresholdTicks = -1;
private boolean enabled = true;
+ private boolean reuse;
EventParser(TimeConverter timeConverter, EventType type, Parser[] parsers) {
this.timeConverter = timeConverter;
@@ -56,6 +58,7 @@
this.hasDuration = type.getField(FIELD_DURATION) != null;
this.startIndex = hasDuration ? 2 : 1;
this.valueDescriptors = type.getFields();
+ this.event = new RecordedEvent(type, valueDescriptors, new Object[parsers.length], 0L, 0L, timeConverter);
}
public EventType getEventType() {
@@ -84,24 +87,44 @@
return null;
}
}
- Object[] values = new Object[parsers.length];
- for (int i = startIndex; i < parsers.length; i++) {
- values[i] = parsers[i].parse(input);
- }
- values[0] = startTicks;
- if (hasDuration) {
- values[1] = Long.valueOf(durationTicks);
- }
- long startTime = timeConverter.convertTimestamp(startTicks);
- if (hasDuration) {
- long endTime = timeConverter.convertTimestamp(startTicks + durationTicks);
- return new RecordedEvent(eventType, valueDescriptors, values, startTime, endTime, timeConverter);
+ if (reuse) {
+ Object[] values = event.objects;
+ for (int i = startIndex; i < parsers.length; i++) {
+ values[i] = parsers[i].parse(input);
+ }
+ values[0] = startTicks;
+ if (hasDuration) {
+ values[1] = Long.valueOf(durationTicks);
+ }
+ long startTime = timeConverter.convertTimestamp(startTicks);
+ if (hasDuration) {
+ event.startTime = startTime;
+ event.endTime = timeConverter.convertTimestamp(startTicks + durationTicks);
+ return event;
+ } else {
+ event.startTime = startTime;
+ event.endTime = startTime;
+ return event;
+ }
} else {
- return new RecordedEvent(eventType, valueDescriptors, values, startTime, startTime, timeConverter);
+ Object[] values = new Object[parsers.length];
+ for (int i = startIndex; i < parsers.length; i++) {
+ values[i] = parsers[i].parse(input);
+ }
+ values[0] = startTicks;
+ if (hasDuration) {
+ values[1] = Long.valueOf(durationTicks);
+ }
+ long startTime = timeConverter.convertTimestamp(startTicks);
+ if (hasDuration) {
+ long endTime = timeConverter.convertTimestamp(startTicks + durationTicks);
+ return new RecordedEvent(eventType, valueDescriptors, values, startTime, endTime, timeConverter);
+ } else {
+ return new RecordedEvent(eventType, valueDescriptors, values, startTime, startTime, timeConverter);
+ }
}
}
- return null;
-
+ return event;
}
@Override
@@ -109,4 +132,8 @@
throw new InternalError("Should not call this method. More efficent to read event size and skip ahead");
}
+ public void setReuse(boolean reuse) {
+ this.reuse = reuse;
+ }
+
}
--- a/src/jdk.jfr/share/classes/jdk/jfr/consumer/EventSet.java Fri May 24 20:51:28 2019 +0200
+++ b/src/jdk.jfr/share/classes/jdk/jfr/consumer/EventSet.java Mon May 27 18:33:13 2019 +0200
@@ -159,7 +159,7 @@
// held with lock
private void addSegment(int index) throws IOException {
if (chunkParser == null) {
- chunkParser = new ChunkParser(new RecordingInput(path.toFile()));
+ chunkParser = new ChunkParser(new RecordingInput(path.toFile()), false);
}
if (dirtyFilter) {
chunkParser.setParserFilter(globalFilter);
--- a/src/jdk.jfr/share/classes/jdk/jfr/consumer/EventStream.java Fri May 24 20:51:28 2019 +0200
+++ b/src/jdk.jfr/share/classes/jdk/jfr/consumer/EventStream.java Mon May 27 18:33:13 2019 +0200
@@ -45,8 +45,8 @@
*/
public static EventStream openRepository(Path directory) throws IOException {
throw new UnsupportedOperationException("Not yet implemented");
-// AccessControlContext acc = AccessController.getContext();
-// return new EventDirectoryStream(acc);
+ // AccessControlContext acc = AccessController.getContext();
+ // return new EventDirectoryStream(acc);
}
/**
@@ -55,11 +55,12 @@
* @param file location of the file, not {@code null}
* @return an event stream, not {@code null}
*
- * @throws IOException if a stream can't be opened,or an I/O error occurs during reading
+ * @throws IOException if a stream can't be opened,or an I/O error occurs
+ * during reading
*/
public static EventStream openFile(Path file) throws IOException {
throw new UnsupportedOperationException("Not yet implemented");
-// return new EventFileStream(file);
+ // return new EventFileStream(file);
}
/**
@@ -67,24 +68,23 @@
*
* @param file location of the file, not {@code null}
*
- * @param the start start time for the stream, or {@code null} to get data from
- * the beginning of the
+ * @param the start start time for the stream, or {@code null} to get data
+ * from the beginning of the
*
- * @param the end end time for the stream, or {@code null} to get data until the
- * end.
+ * @param the end end time for the stream, or {@code null} to get data until
+ * the end.
*
* @throws IllegalArgumentException if {@code end} happens before
* {@code start}
*
- * @throws IOException if a stream can't be opened,or an I/O error occurs during reading
+ * @throws IOException if a stream can't be opened,or an I/O error occurs
+ * during reading
*/
public static EventStream openFile(Path file, Instant from, Instant to) throws IOException {
throw new UnsupportedOperationException("Not yet implemented");
-// return new EventFileStream(file);
+ // return new EventFileStream(file);
}
-
-
/**
* Performs an action on all events in the stream.
*
@@ -140,6 +140,19 @@
boolean remove(Object action);
/**
+ * Hint that the the event object in an {@link #onEvent(Consumer)} action
+ * may be reused.
+ * <p>
+ * If reuse is set to
+ * {@code true), a callback should not keep a reference to the event object
+ * after the callback from {@code onEvent} has returned.
+ * <p>
+ * By default reuse is {@code true}
+ *
+ */
+ public void setReuse(boolean reuse);
+
+ /**
* Starts processing events in the stream.
* <p>
* All actions will performed on this stream will happen in the current
--- a/src/jdk.jfr/share/classes/jdk/jfr/consumer/RecordedEvent.java Fri May 24 20:51:28 2019 +0200
+++ b/src/jdk.jfr/share/classes/jdk/jfr/consumer/RecordedEvent.java Mon May 27 18:33:13 2019 +0200
@@ -40,9 +40,8 @@
*/
public final class RecordedEvent extends RecordedObject {
private final EventType eventType;
- private final long startTime;
- // package private needed for efficient sorting
- final long endTime;
+ long startTime;
+ long endTime;
// package private
RecordedEvent(EventType type, List<ValueDescriptor> vds, Object[] values, long startTime, long endTime, TimeConverter timeConverter) {
--- a/src/jdk.jfr/share/classes/jdk/jfr/consumer/RecordedObject.java Fri May 24 20:51:28 2019 +0200
+++ b/src/jdk.jfr/share/classes/jdk/jfr/consumer/RecordedObject.java Mon May 27 18:33:13 2019 +0200
@@ -95,7 +95,7 @@
}
}
- private final Object[] objects;
+ final Object[] objects;
private final List<ValueDescriptor> descriptors;
private final TimeConverter timeConverter;
--- a/src/jdk.jfr/share/classes/jdk/jfr/consumer/RecordingFile.java Fri May 24 20:51:28 2019 +0200
+++ b/src/jdk.jfr/share/classes/jdk/jfr/consumer/RecordingFile.java Mon May 27 18:33:13 2019 +0200
@@ -237,7 +237,7 @@
private void findNext() throws IOException {
while (nextEvent == null) {
if (chunkParser == null) {
- chunkParser = new ChunkParser(input);
+ chunkParser = new ChunkParser(input, false);
} else if (!chunkParser.isLastChunk()) {
chunkParser = chunkParser.nextChunkParser();
} else {
--- a/src/jdk.jfr/share/classes/jdk/jfr/consumer/RecordingStream.java Fri May 24 20:51:28 2019 +0200
+++ b/src/jdk.jfr/share/classes/jdk/jfr/consumer/RecordingStream.java Mon May 27 18:33:13 2019 +0200
@@ -296,4 +296,9 @@
public void awaitTermination() {
stream.awaitTermination();
}
+
+ @Override
+ public void setReuse(boolean reuse) {
+ // hint is ignored
+ }
}