diff options
author | shahan <shahan@google.com> | 2018-05-14 21:51:47 -0700 |
---|---|---|
committer | Copybara-Service <copybara-piper@google.com> | 2018-05-14 21:53:39 -0700 |
commit | 150a9065620cc66c19ccc8c663d4fb41bb82a1ca (patch) | |
tree | 15e5b78f94eacb4988b83f3abd491231328262d5 | |
parent | eb5a80c7ba8f139f293d12147aec683de8582bc0 (diff) |
DynamicCodec tweaks to make it into a super fast String serializer.
(3-8x faster than StringCodec).
PiperOrigin-RevId: 196615858
-rw-r--r-- | src/main/java/com/google/devtools/build/lib/skyframe/serialization/DynamicCodec.java | 51 |
1 files changed, 41 insertions, 10 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/serialization/DynamicCodec.java b/src/main/java/com/google/devtools/build/lib/skyframe/serialization/DynamicCodec.java index c4301a8fe4..47e9a69e64 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/serialization/DynamicCodec.java +++ b/src/main/java/com/google/devtools/build/lib/skyframe/serialization/DynamicCodec.java @@ -14,7 +14,6 @@ package com.google.devtools.build.lib.skyframe.serialization; -import com.google.common.collect.ImmutableSortedMap; import com.google.devtools.build.lib.skyframe.serialization.autocodec.UnsafeProvider; import com.google.protobuf.CodedInputStream; import com.google.protobuf.CodedOutputStream; @@ -26,6 +25,7 @@ import java.lang.reflect.Modifier; import java.nio.ByteBuffer; import java.util.Comparator; import java.util.Map; +import java.util.TreeMap; import sun.reflect.ReflectionFactory; /** @@ -37,7 +37,7 @@ public class DynamicCodec implements ObjectCodec<Object> { private final Class<?> type; private final Constructor<?> constructor; - private final ImmutableSortedMap<Field, Long> offsets; + private final TypeAndOffset[] offsets; public DynamicCodec(Class<?> type) throws ReflectiveOperationException { this.type = type; @@ -58,8 +58,8 @@ public class DynamicCodec implements ObjectCodec<Object> { @Override public void serialize(SerializationContext context, Object obj, CodedOutputStream codedOut) throws SerializationException, IOException { - for (Map.Entry<Field, Long> entry : offsets.entrySet()) { - serializeField(context, codedOut, obj, entry.getKey().getType(), entry.getValue()); + for (int i = 0; i < offsets.length; ++i) { + serializeField(context, codedOut, obj, offsets[i].type, offsets[i].offset); } } @@ -105,6 +105,15 @@ public class DynamicCodec implements ObjectCodec<Object> { } } else if (type.isArray()) { Object arr = UnsafeProvider.getInstance().getObject(obj, offset); + if (type.getComponentType().equals(byte.class)) { + if (arr == null) { + codedOut.writeBoolNoTag(false); + } else { + codedOut.writeBoolNoTag(true); + codedOut.writeByteArrayNoTag((byte[]) arr); + } + return; + } if (arr == null) { codedOut.writeInt32NoTag(-1); return; @@ -140,8 +149,8 @@ public class DynamicCodec implements ObjectCodec<Object> { throw new SerializationException("Could not instantiate object of type: " + type, e); } context.registerInitialValue(instance); - for (Map.Entry<Field, Long> entry : offsets.entrySet()) { - deserializeField(context, codedIn, instance, entry.getKey().getType(), entry.getValue()); + for (int i = 0; i < offsets.length; ++i) { + deserializeField(context, codedIn, instance, offsets[i].type, offsets[i].offset); } return instance; } @@ -185,6 +194,12 @@ public class DynamicCodec implements ObjectCodec<Object> { throw new UnsupportedOperationException("Unknown primitive type: " + type); } } else if (type.isArray()) { + if (type.getComponentType().equals(byte.class)) { + boolean isNonNull = codedIn.readBool(); + UnsafeProvider.getInstance() + .putObject(obj, offset, isNonNull ? codedIn.readByteArray() : null); + return; + } int length = codedIn.readInt32(); if (length < 0) { UnsafeProvider.getInstance().putObject(obj, offset, null); @@ -206,9 +221,8 @@ public class DynamicCodec implements ObjectCodec<Object> { } } - private static <T> ImmutableSortedMap<Field, Long> getOffsets(Class<T> type) { - ImmutableSortedMap.Builder<Field, Long> offsets = - new ImmutableSortedMap.Builder<>(new FieldComparator()); + private static <T> TypeAndOffset[] getOffsets(Class<T> type) { + TreeMap<Field, Long> offsets = new TreeMap<>(new FieldComparator()); for (Class<? super T> next = type; next != null; next = next.getSuperclass()) { for (Field field : next.getDeclaredFields()) { if ((field.getModifiers() & (Modifier.STATIC | Modifier.TRANSIENT)) != 0) { @@ -218,7 +232,24 @@ public class DynamicCodec implements ObjectCodec<Object> { offsets.put(field, UnsafeProvider.getInstance().objectFieldOffset(field)); } } - return offsets.build(); + // Converts to an array to make it easy to avoid the use of iterators. + TypeAndOffset[] offsetsArr = new TypeAndOffset[offsets.size()]; + int i = 0; + for (Map.Entry<Field, Long> entry : offsets.entrySet()) { + offsetsArr[i] = new TypeAndOffset(entry.getKey().getType(), entry.getValue()); + ++i; + } + return offsetsArr; + } + + private static class TypeAndOffset { + public final Class<?> type; + public final long offset; + + public TypeAndOffset(Class<?> type, long offset) { + this.type = type; + this.offset = offset; + } } private static Constructor<?> getConstructor(Class<?> type) throws ReflectiveOperationException { |