aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar shahan <shahan@google.com>2018-05-14 21:51:47 -0700
committerGravatar Copybara-Service <copybara-piper@google.com>2018-05-14 21:53:39 -0700
commit150a9065620cc66c19ccc8c663d4fb41bb82a1ca (patch)
tree15e5b78f94eacb4988b83f3abd491231328262d5
parenteb5a80c7ba8f139f293d12147aec683de8582bc0 (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.java51
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 {