# HG changeset patch # User egahlin # Date 1562620085 -7200 # Node ID bcbc53560c77df64f92a32b6d485e1d4e0d2bbfb # Parent df39f8d8f4d6c63ae89aa392b2b1207b6500fa8d Reduce allocation rate by minimizing number of fields in RecordedEvent diff -r df39f8d8f4d6 -r bcbc53560c77 src/jdk.jfr/share/classes/jdk/jfr/consumer/EventParser.java --- a/src/jdk.jfr/share/classes/jdk/jfr/consumer/EventParser.java Mon Jul 08 18:11:26 2019 +0200 +++ b/src/jdk.jfr/share/classes/jdk/jfr/consumer/EventParser.java Mon Jul 08 23:08:05 2019 +0200 @@ -54,6 +54,7 @@ private boolean ordered; private long firstNanos; private long thresholdNanos = -1; + private ObjectContext objectContext; EventParser(TimeConverter timeConverter, EventType type, Parser[] parsers) { this.timeConverter = timeConverter; @@ -63,7 +64,8 @@ this.startIndex = hasDuration ? 2 : 1; this.length = parsers.length - startIndex; this.valueDescriptors = type.getFields(); - this.unorderedEvent = new RecordedEvent(eventType, valueDescriptors, new Object[length], 0L, 0L, timeConverter); + this.objectContext = new ObjectContext(type, valueDescriptors, timeConverter); + this.unorderedEvent = new RecordedEvent(objectContext, new Object[length], 0L, 0L); } private RecordedEvent cachedEvent() { @@ -75,7 +77,7 @@ } RecordedEvent event = eventCache[index]; if (event == null) { - event = new RecordedEvent(eventType, valueDescriptors, new Object[length], 0L, 0L, timeConverter); + event = new RecordedEvent(objectContext, new Object[length], 0L, 0L); eventCache[index] = event; } index++; @@ -134,7 +136,7 @@ for (int i = 0; i < length; i++) { values[i] = parsers[startIndex + i].parse(input); } - return new RecordedEvent(eventType, valueDescriptors, values, startTicks, endTicks, timeConverter); + return new RecordedEvent(objectContext, values, startTicks, endTicks); } } return null; diff -r df39f8d8f4d6 -r bcbc53560c77 src/jdk.jfr/share/classes/jdk/jfr/consumer/ObjectFactory.java --- a/src/jdk.jfr/share/classes/jdk/jfr/consumer/ObjectFactory.java Mon Jul 08 18:11:26 2019 +0200 +++ b/src/jdk.jfr/share/classes/jdk/jfr/consumer/ObjectFactory.java Mon Jul 08 23:08:05 2019 +0200 @@ -25,9 +25,6 @@ package jdk.jfr.consumer; -import java.util.List; - -import jdk.jfr.ValueDescriptor; import jdk.jfr.internal.Type; /** @@ -65,10 +62,10 @@ return null; } - private final List valueDescriptors; + private final ObjectContext objectContext; - ObjectFactory(Type type) { - this.valueDescriptors = type.getFields(); + ObjectFactory(Type type, TimeConverter timeConverter) { + this.objectContext = new ObjectContext(null, type.getFields(), timeConverter); } T createObject(long id, Object value) { @@ -76,10 +73,10 @@ return null; } if (value instanceof Object[]) { - return createTyped(valueDescriptors, id, (Object[]) value); + return createTyped(objectContext, id, (Object[]) value); } throw new InternalError("Object factory must have struct type. Type was " + value.getClass().getName()); } - abstract T createTyped(List valueDescriptors, long id, Object[] values); + abstract T createTyped(ObjectContext objectContextm, long id, Object[] values); } diff -r df39f8d8f4d6 -r bcbc53560c77 src/jdk.jfr/share/classes/jdk/jfr/consumer/RecordedClass.java --- a/src/jdk.jfr/share/classes/jdk/jfr/consumer/RecordedClass.java Mon Jul 08 18:11:26 2019 +0200 +++ b/src/jdk.jfr/share/classes/jdk/jfr/consumer/RecordedClass.java Mon Jul 08 23:08:05 2019 +0200 @@ -26,9 +26,7 @@ package jdk.jfr.consumer; import java.lang.reflect.Modifier; -import java.util.List; -import jdk.jfr.ValueDescriptor; import jdk.jfr.internal.Type; /** @@ -39,10 +37,10 @@ public final class RecordedClass extends RecordedObject { static ObjectFactory createFactory(Type type, TimeConverter timeConverter) { - return new ObjectFactory(type) { + return new ObjectFactory(type, timeConverter) { @Override - RecordedClass createTyped(List desc, long id, Object[] object) { - return new RecordedClass(desc, id, object, timeConverter); + RecordedClass createTyped(ObjectContext objectContext, long id, Object[] values) { + return new RecordedClass(objectContext, id, values); } }; } @@ -50,8 +48,8 @@ private final long uniqueId; // package private - private RecordedClass(List descriptors, long id, Object[] values, TimeConverter timeConverter) { - super(descriptors, values, timeConverter); + private RecordedClass(ObjectContext objectContext, long id, Object[] values) { + super(objectContext, values); this.uniqueId = id; } diff -r df39f8d8f4d6 -r bcbc53560c77 src/jdk.jfr/share/classes/jdk/jfr/consumer/RecordedClassLoader.java --- a/src/jdk.jfr/share/classes/jdk/jfr/consumer/RecordedClassLoader.java Mon Jul 08 18:11:26 2019 +0200 +++ b/src/jdk.jfr/share/classes/jdk/jfr/consumer/RecordedClassLoader.java Mon Jul 08 23:08:05 2019 +0200 @@ -25,9 +25,6 @@ package jdk.jfr.consumer; -import java.util.List; - -import jdk.jfr.ValueDescriptor; import jdk.jfr.internal.Type; /** @@ -38,10 +35,10 @@ public final class RecordedClassLoader extends RecordedObject { static ObjectFactory createFactory(Type type, TimeConverter timeConverter) { - return new ObjectFactory(type) { + return new ObjectFactory(type, timeConverter) { @Override - RecordedClassLoader createTyped(List desc, long id, Object[] object) { - return new RecordedClassLoader(desc, id, object, timeConverter); + RecordedClassLoader createTyped(ObjectContext objectContext, long id, Object[] values) { + return new RecordedClassLoader(objectContext, id, values); } }; } @@ -49,8 +46,8 @@ private final long uniqueId; // package private - private RecordedClassLoader(List descriptors, long id, Object[] values, TimeConverter timeConverter) { - super(descriptors, values, timeConverter); + private RecordedClassLoader(ObjectContext objectContext, long id, Object[] values) { + super(objectContext, values); this.uniqueId = id; } diff -r df39f8d8f4d6 -r bcbc53560c77 src/jdk.jfr/share/classes/jdk/jfr/consumer/RecordedEvent.java --- a/src/jdk.jfr/share/classes/jdk/jfr/consumer/RecordedEvent.java Mon Jul 08 18:11:26 2019 +0200 +++ b/src/jdk.jfr/share/classes/jdk/jfr/consumer/RecordedEvent.java Mon Jul 08 23:08:05 2019 +0200 @@ -39,14 +39,12 @@ * @since 9 */ public final class RecordedEvent extends RecordedObject { - private final EventType eventType; long startTimeTicks; long endTimeTicks; // package private - RecordedEvent(EventType type, List vds, Object[] values, long startTimeTicks, long endTimeTicks, TimeConverter timeConverter) { - super(vds, values, timeConverter); - this.eventType = type; + RecordedEvent(ObjectContext objectContext, Object[] values, long startTimeTicks, long endTimeTicks) { + super(objectContext, values); this.startTimeTicks = startTimeTicks; this.endTimeTicks = endTimeTicks; } @@ -77,7 +75,7 @@ * @return the event type, not {@code null} */ public EventType getEventType() { - return eventType; + return objectContext.eventType; } /** @@ -118,7 +116,7 @@ */ @Override public List getFields() { - return getEventType().getFields(); + return objectContext.fields; } protected final Object objectAt(int index) { @@ -135,14 +133,14 @@ } private boolean hasDuration() { - return objects.length + 2 == descriptors.size(); + return objects.length + 2 == objectContext.fields.size(); } private long getStartTimeNanos() { - return timeConverter.convertTimestamp(startTimeTicks); + return objectContext.timeConverter.convertTimestamp(startTimeTicks); } private long getEndTimeNanos() { - return timeConverter.convertTimestamp(endTimeTicks); + return objectContext.timeConverter.convertTimestamp(endTimeTicks); } } diff -r df39f8d8f4d6 -r bcbc53560c77 src/jdk.jfr/share/classes/jdk/jfr/consumer/RecordedFrame.java --- a/src/jdk.jfr/share/classes/jdk/jfr/consumer/RecordedFrame.java Mon Jul 08 18:11:26 2019 +0200 +++ b/src/jdk.jfr/share/classes/jdk/jfr/consumer/RecordedFrame.java Mon Jul 08 23:08:05 2019 +0200 @@ -26,9 +26,7 @@ package jdk.jfr.consumer; import java.lang.reflect.Modifier; -import java.util.List; -import jdk.jfr.ValueDescriptor; import jdk.jfr.internal.Type; /** @@ -39,17 +37,17 @@ public final class RecordedFrame extends RecordedObject { static ObjectFactory createFactory(Type type, TimeConverter timeConverter) { - return new ObjectFactory(type) { + return new ObjectFactory(type, timeConverter) { @Override - RecordedFrame createTyped(List desc, long id, Object[] object) { - return new RecordedFrame(desc, object, timeConverter); + RecordedFrame createTyped(ObjectContext objectContext, long id, Object[] values) { + return new RecordedFrame(objectContext, values); } }; } // package private - RecordedFrame(List desc, Object[] objects, TimeConverter timeConverter) { - super(desc, objects, timeConverter); + RecordedFrame(ObjectContext objectContext, Object[] objects) { + super(objectContext, objects); } /** diff -r df39f8d8f4d6 -r bcbc53560c77 src/jdk.jfr/share/classes/jdk/jfr/consumer/RecordedMethod.java --- a/src/jdk.jfr/share/classes/jdk/jfr/consumer/RecordedMethod.java Mon Jul 08 18:11:26 2019 +0200 +++ b/src/jdk.jfr/share/classes/jdk/jfr/consumer/RecordedMethod.java Mon Jul 08 23:08:05 2019 +0200 @@ -26,9 +26,7 @@ package jdk.jfr.consumer; import java.lang.reflect.Modifier; -import java.util.List; -import jdk.jfr.ValueDescriptor; import jdk.jfr.internal.Type; /** @@ -39,16 +37,16 @@ public final class RecordedMethod extends RecordedObject { static ObjectFactory createFactory(Type type, TimeConverter timeConverter) { - return new ObjectFactory(type) { + return new ObjectFactory(type, timeConverter) { @Override - RecordedMethod createTyped(List desc, long id, Object[] object) { - return new RecordedMethod(desc, object, timeConverter); + RecordedMethod createTyped(ObjectContext objectContext, long id, Object[] values) { + return new RecordedMethod(objectContext, values); } }; } - private RecordedMethod(List descriptors, Object[] objects, TimeConverter timeConverter) { - super(descriptors, objects, timeConverter); + private RecordedMethod(ObjectContext objectContext, Object[] values) { + super(objectContext, values); } /** diff -r df39f8d8f4d6 -r bcbc53560c77 src/jdk.jfr/share/classes/jdk/jfr/consumer/RecordedObject.java --- a/src/jdk.jfr/share/classes/jdk/jfr/consumer/RecordedObject.java Mon Jul 08 18:11:26 2019 +0200 +++ b/src/jdk.jfr/share/classes/jdk/jfr/consumer/RecordedObject.java Mon Jul 08 23:08:05 2019 +0200 @@ -96,14 +96,12 @@ } final Object[] objects; - protected final List descriptors; - protected final TimeConverter timeConverter; + final ObjectContext objectContext; // package private, not to be subclassed outside this package - RecordedObject(List descriptors, Object[] objects, TimeConverter timeConverter) { - this.descriptors = descriptors; + RecordedObject(ObjectContext objectContext, Object[] objects) { + this.objectContext = objectContext; this.objects = objects; - this.timeConverter = timeConverter; } // package private @@ -133,7 +131,7 @@ */ public boolean hasField(String name) { Objects.requireNonNull(name); - for (ValueDescriptor v : descriptors) { + for (ValueDescriptor v : objectContext.fields) { if (v.getName().equals(name)) { return true; } @@ -141,7 +139,7 @@ int dotIndex = name.indexOf("."); if (dotIndex > 0) { String structName = name.substring(0, dotIndex); - for (ValueDescriptor v : descriptors) { + for (ValueDescriptor v : objectContext.fields) { if (!v.getFields().isEmpty() && v.getName().equals(structName)) { RecordedObject child = getValue(structName); if (child != null) { @@ -208,7 +206,7 @@ private Object getValue(String name, boolean allowUnsigned) { Objects.requireNonNull(name); int index = 0; - for (ValueDescriptor v : descriptors) { + for (ValueDescriptor v : objectContext.fields) { if (name.equals(v.getName())) { Object object = objectAt(index); if (object == null) { @@ -236,7 +234,7 @@ return structifyArray(v, array, 0); } // struct - return new RecordedObject(v.getFields(), (Object[]) object, timeConverter); + return new RecordedObject(objectContext.getInstance(v), (Object[]) object); } } index++; @@ -245,7 +243,7 @@ int dotIndex = name.indexOf("."); if (dotIndex > 0) { String structName = name.substring(0, dotIndex); - for (ValueDescriptor v : descriptors) { + for (ValueDescriptor v : objectContext.fields) { if (!v.getFields().isEmpty() && v.getName().equals(structName)) { RecordedObject child = getValue(structName); String subName = name.substring(dotIndex + 1); @@ -297,7 +295,7 @@ private T getTypedValue(String name, String typeName) { Objects.requireNonNull(name); // Validate name and type first - getValueDescriptor(descriptors, name, typeName); + getValueDescriptor(objectContext.fields, name, typeName); return getValue(name); } @@ -306,15 +304,16 @@ return null; } Object[] structArray = new Object[array.length]; + ObjectContext objContext = objectContext.getInstance(v); for (int i = 0; i < structArray.length; i++) { Object arrayElement = array[i]; if (dimension == 0) { // No general way to handle structarrays // without invoking ObjectFactory for every instance (which may require id) if (isStackFrameType(v.getTypeName())) { - structArray[i] = new RecordedFrame(v.getFields(), (Object[]) arrayElement, timeConverter); + structArray[i] = new RecordedFrame(objContext, (Object[]) arrayElement); } else { - structArray[i] = new RecordedObject(v.getFields(), (Object[]) arrayElement, timeConverter); + structArray[i] = new RecordedObject(objContext, (Object[]) arrayElement); } } else { structArray[i] = structifyArray(v, (Object[]) arrayElement, dimension - 1); @@ -339,7 +338,7 @@ * @return the fields, not {@code null} */ public List getFields() { - return descriptors; + return objectContext.fields; } /** @@ -761,7 +760,7 @@ } private Duration getDuration(long timespan, String name) throws InternalError { - ValueDescriptor v = getValueDescriptor(descriptors, name, null); + ValueDescriptor v = getValueDescriptor(objectContext.fields, name, null); if (timespan == Long.MIN_VALUE) { return Duration.ofSeconds(Long.MIN_VALUE, 0); } @@ -777,7 +776,7 @@ case Timespan.NANOSECONDS: return Duration.ofNanos(timespan); case Timespan.TICKS: - return Duration.ofNanos(timeConverter.convertTimespan(timespan)); + return Duration.ofNanos(objectContext.timeConverter.convertTimespan(timespan)); } throw new IllegalArgumentException("Attempt to get " + v.getTypeName() + " field \"" + name + "\" with illegal timespan unit " + ts.value()); } @@ -840,7 +839,7 @@ } private Instant getInstant(long timestamp, String name) { - ValueDescriptor v = getValueDescriptor(descriptors, name, null); + ValueDescriptor v = getValueDescriptor(objectContext.fields, name, null); Timestamp ts = v.getAnnotation(Timestamp.class); if (ts != null) { if (timestamp == Long.MIN_VALUE) { @@ -850,7 +849,7 @@ case Timestamp.MILLISECONDS_SINCE_EPOCH: return Instant.ofEpochMilli(timestamp); case Timestamp.TICKS: - return Instant.ofEpochSecond(0, timeConverter.convertTimestamp(timestamp)); + return Instant.ofEpochSecond(0, objectContext.timeConverter.convertTimestamp(timestamp)); } throw new IllegalArgumentException("Attempt to get " + v.getTypeName() + " field \"" + name + "\" with illegal timestamp unit " + ts.value()); } @@ -930,7 +929,7 @@ if (instant.equals(Instant.MIN)) { return OffsetDateTime.MIN; } - return OffsetDateTime.ofInstant(getInstant(name), timeConverter.getZoneOffset()); + return OffsetDateTime.ofInstant(getInstant(name), objectContext.timeConverter.getZoneOffset()); } private static IllegalArgumentException newIllegalArgumentException(String name, String typeName) { diff -r df39f8d8f4d6 -r bcbc53560c77 src/jdk.jfr/share/classes/jdk/jfr/consumer/RecordedStackTrace.java --- a/src/jdk.jfr/share/classes/jdk/jfr/consumer/RecordedStackTrace.java Mon Jul 08 18:11:26 2019 +0200 +++ b/src/jdk.jfr/share/classes/jdk/jfr/consumer/RecordedStackTrace.java Mon Jul 08 23:08:05 2019 +0200 @@ -29,7 +29,6 @@ import java.util.Collections; import java.util.List; -import jdk.jfr.ValueDescriptor; import jdk.jfr.internal.Type; /** @@ -40,16 +39,16 @@ public final class RecordedStackTrace extends RecordedObject { static ObjectFactory createFactory(Type type, TimeConverter timeConverter) { - return new ObjectFactory(type) { + return new ObjectFactory(type, timeConverter) { @Override - RecordedStackTrace createTyped(List desc, long id, Object[] object) { - return new RecordedStackTrace(desc, object, timeConverter); + RecordedStackTrace createTyped(ObjectContext objectContext, long id, Object[] values) { + return new RecordedStackTrace(objectContext, values); } }; } - private RecordedStackTrace(List desc, Object[] values, TimeConverter timeConverter) { - super(desc, values, timeConverter); + private RecordedStackTrace(ObjectContext objectContext, Object[] values) { + super(objectContext, values); } /** diff -r df39f8d8f4d6 -r bcbc53560c77 src/jdk.jfr/share/classes/jdk/jfr/consumer/RecordedThread.java --- a/src/jdk.jfr/share/classes/jdk/jfr/consumer/RecordedThread.java Mon Jul 08 18:11:26 2019 +0200 +++ b/src/jdk.jfr/share/classes/jdk/jfr/consumer/RecordedThread.java Mon Jul 08 23:08:05 2019 +0200 @@ -25,9 +25,6 @@ package jdk.jfr.consumer; -import java.util.List; - -import jdk.jfr.ValueDescriptor; import jdk.jfr.internal.Type; /** @@ -38,18 +35,18 @@ public final class RecordedThread extends RecordedObject { static ObjectFactory createFactory(Type type, TimeConverter timeConverter) { - return new ObjectFactory(type) { + return new ObjectFactory(type, timeConverter) { @Override - RecordedThread createTyped(List desc, long id, Object[] object) { - return new RecordedThread(desc, id, object, timeConverter); + RecordedThread createTyped(ObjectContext objectContext, long id, Object[] values) { + return new RecordedThread(objectContext, id, values); } }; } private final long uniqueId; - private RecordedThread(List descriptors, long id, Object[] values, TimeConverter timeConverter) { - super(descriptors, values, timeConverter); + private RecordedThread(ObjectContext objectContext, long id, Object[] values) { + super(objectContext, values); this.uniqueId = id; } diff -r df39f8d8f4d6 -r bcbc53560c77 src/jdk.jfr/share/classes/jdk/jfr/consumer/RecordedThreadGroup.java --- a/src/jdk.jfr/share/classes/jdk/jfr/consumer/RecordedThreadGroup.java Mon Jul 08 18:11:26 2019 +0200 +++ b/src/jdk.jfr/share/classes/jdk/jfr/consumer/RecordedThreadGroup.java Mon Jul 08 23:08:05 2019 +0200 @@ -25,9 +25,6 @@ package jdk.jfr.consumer; -import java.util.List; - -import jdk.jfr.ValueDescriptor; import jdk.jfr.internal.Type; /** @@ -38,16 +35,16 @@ public final class RecordedThreadGroup extends RecordedObject { static ObjectFactory createFactory(Type type, TimeConverter timeConverter) { - return new ObjectFactory(type) { + return new ObjectFactory(type, timeConverter) { @Override - RecordedThreadGroup createTyped(List desc, long id, Object[] object) { - return new RecordedThreadGroup(desc, object, timeConverter); + RecordedThreadGroup createTyped(ObjectContext objectContext, long id, Object[] values) { + return new RecordedThreadGroup(objectContext, values); } }; } - private RecordedThreadGroup(List descriptors, Object[] objects, TimeConverter timeConverter) { - super(descriptors, objects, timeConverter); + private RecordedThreadGroup(ObjectContext objectContext, Object[] values) { + super(objectContext, values); } /**