Switch Parcel to FastNative
Also fixes ParcelBenchmark to have bounded
memory usage to avoid OOM'ing during runs
Test: refactor, no behavior change
ParcelBenchmark results from bullhead
Before:
timeReadByte 74.43ns
timeReadInt 74.49ns
timeReadLong 74.13ns
timeWriteByte 81.81ns
timeWriteInt 82.09ns
timeWriteLong 81.84ns
After:
timeReadByte 47.08ns
timeReadInt 48.38ns
timeReadLong 48.16ns
timeWriteByte 55.90ns
timeWriteInt 55.85ns
timeWriteLong 56.58ns
Change-Id: I61b823d1d2beb86e00c196abd4dce65efa8fa7f0
diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java
index f6e6ad6..85f999b 100644
--- a/core/java/android/os/Parcel.java
+++ b/core/java/android/os/Parcel.java
@@ -46,6 +46,7 @@
import java.util.Map;
import java.util.Set;
+import dalvik.annotation.optimization.FastNative;
import dalvik.system.VMRuntime;
/**
@@ -254,22 +255,35 @@
// see libbinder's binder/Status.h
private static final int EX_TRANSACTION_FAILED = -129;
+ @FastNative
private static native int nativeDataSize(long nativePtr);
+ @FastNative
private static native int nativeDataAvail(long nativePtr);
+ @FastNative
private static native int nativeDataPosition(long nativePtr);
+ @FastNative
private static native int nativeDataCapacity(long nativePtr);
+ @FastNative
private static native long nativeSetDataSize(long nativePtr, int size);
+ @FastNative
private static native void nativeSetDataPosition(long nativePtr, int pos);
+ @FastNative
private static native void nativeSetDataCapacity(long nativePtr, int size);
+ @FastNative
private static native boolean nativePushAllowFds(long nativePtr, boolean allowFds);
+ @FastNative
private static native void nativeRestoreAllowFds(long nativePtr, boolean lastValue);
private static native void nativeWriteByteArray(long nativePtr, byte[] b, int offset, int len);
private static native void nativeWriteBlob(long nativePtr, byte[] b, int offset, int len);
+ @FastNative
private static native void nativeWriteInt(long nativePtr, int val);
+ @FastNative
private static native void nativeWriteLong(long nativePtr, long val);
+ @FastNative
private static native void nativeWriteFloat(long nativePtr, float val);
+ @FastNative
private static native void nativeWriteDouble(long nativePtr, double val);
private static native void nativeWriteString(long nativePtr, String val);
private static native void nativeWriteStrongBinder(long nativePtr, IBinder val);
@@ -277,9 +291,13 @@
private static native byte[] nativeCreateByteArray(long nativePtr);
private static native byte[] nativeReadBlob(long nativePtr);
+ @FastNative
private static native int nativeReadInt(long nativePtr);
+ @FastNative
private static native long nativeReadLong(long nativePtr);
+ @FastNative
private static native float nativeReadFloat(long nativePtr);
+ @FastNative
private static native double nativeReadDouble(long nativePtr);
private static native String nativeReadString(long nativePtr);
private static native IBinder nativeReadStrongBinder(long nativePtr);
@@ -294,6 +312,7 @@
long nativePtr, byte[] data, int offset, int length);
private static native long nativeAppendFrom(
long thisNativePtr, long otherNativePtr, int offset, int length);
+ @FastNative
private static native boolean nativeHasFileDescriptors(long nativePtr);
private static native void nativeWriteInterfaceToken(long nativePtr, String interfaceName);
private static native void nativeEnforceInterface(long nativePtr, String interfaceName);
diff --git a/core/jni/android_os_Parcel.cpp b/core/jni/android_os_Parcel.cpp
index 0a8ae2b..8f7908a 100644
--- a/core/jni/android_os_Parcel.cpp
+++ b/core/jni/android_os_Parcel.cpp
@@ -722,33 +722,50 @@
// ----------------------------------------------------------------------------
static const JNINativeMethod gParcelMethods[] = {
- {"nativeDataSize", "!(J)I", (void*)android_os_Parcel_dataSize},
- {"nativeDataAvail", "!(J)I", (void*)android_os_Parcel_dataAvail},
- {"nativeDataPosition", "!(J)I", (void*)android_os_Parcel_dataPosition},
- {"nativeDataCapacity", "!(J)I", (void*)android_os_Parcel_dataCapacity},
- {"nativeSetDataSize", "!(JI)J", (void*)android_os_Parcel_setDataSize},
- {"nativeSetDataPosition", "!(JI)V", (void*)android_os_Parcel_setDataPosition},
- {"nativeSetDataCapacity", "!(JI)V", (void*)android_os_Parcel_setDataCapacity},
+ // @FastNative
+ {"nativeDataSize", "(J)I", (void*)android_os_Parcel_dataSize},
+ // @FastNative
+ {"nativeDataAvail", "(J)I", (void*)android_os_Parcel_dataAvail},
+ // @FastNative
+ {"nativeDataPosition", "(J)I", (void*)android_os_Parcel_dataPosition},
+ // @FastNative
+ {"nativeDataCapacity", "(J)I", (void*)android_os_Parcel_dataCapacity},
+ // @FastNative
+ {"nativeSetDataSize", "(JI)J", (void*)android_os_Parcel_setDataSize},
+ // @FastNative
+ {"nativeSetDataPosition", "(JI)V", (void*)android_os_Parcel_setDataPosition},
+ // @FastNative
+ {"nativeSetDataCapacity", "(JI)V", (void*)android_os_Parcel_setDataCapacity},
- {"nativePushAllowFds", "!(JZ)Z", (void*)android_os_Parcel_pushAllowFds},
- {"nativeRestoreAllowFds", "!(JZ)V", (void*)android_os_Parcel_restoreAllowFds},
+ // @FastNative
+ {"nativePushAllowFds", "(JZ)Z", (void*)android_os_Parcel_pushAllowFds},
+ // @FastNative
+ {"nativeRestoreAllowFds", "(JZ)V", (void*)android_os_Parcel_restoreAllowFds},
{"nativeWriteByteArray", "(J[BII)V", (void*)android_os_Parcel_writeNative},
{"nativeWriteBlob", "(J[BII)V", (void*)android_os_Parcel_writeBlob},
- {"nativeWriteInt", "!(JI)V", (void*)android_os_Parcel_writeInt},
- {"nativeWriteLong", "!(JJ)V", (void*)android_os_Parcel_writeLong},
- {"nativeWriteFloat", "!(JF)V", (void*)android_os_Parcel_writeFloat},
- {"nativeWriteDouble", "!(JD)V", (void*)android_os_Parcel_writeDouble},
+ // @FastNative
+ {"nativeWriteInt", "(JI)V", (void*)android_os_Parcel_writeInt},
+ // @FastNative
+ {"nativeWriteLong", "(JJ)V", (void*)android_os_Parcel_writeLong},
+ // @FastNative
+ {"nativeWriteFloat", "(JF)V", (void*)android_os_Parcel_writeFloat},
+ // @FastNative
+ {"nativeWriteDouble", "(JD)V", (void*)android_os_Parcel_writeDouble},
{"nativeWriteString", "(JLjava/lang/String;)V", (void*)android_os_Parcel_writeString},
{"nativeWriteStrongBinder", "(JLandroid/os/IBinder;)V", (void*)android_os_Parcel_writeStrongBinder},
{"nativeWriteFileDescriptor", "(JLjava/io/FileDescriptor;)J", (void*)android_os_Parcel_writeFileDescriptor},
{"nativeCreateByteArray", "(J)[B", (void*)android_os_Parcel_createByteArray},
{"nativeReadBlob", "(J)[B", (void*)android_os_Parcel_readBlob},
- {"nativeReadInt", "!(J)I", (void*)android_os_Parcel_readInt},
- {"nativeReadLong", "!(J)J", (void*)android_os_Parcel_readLong},
- {"nativeReadFloat", "!(J)F", (void*)android_os_Parcel_readFloat},
- {"nativeReadDouble", "!(J)D", (void*)android_os_Parcel_readDouble},
+ // @FastNative
+ {"nativeReadInt", "(J)I", (void*)android_os_Parcel_readInt},
+ // @FastNative
+ {"nativeReadLong", "(J)J", (void*)android_os_Parcel_readLong},
+ // @FastNative
+ {"nativeReadFloat", "(J)F", (void*)android_os_Parcel_readFloat},
+ // @FastNative
+ {"nativeReadDouble", "(J)D", (void*)android_os_Parcel_readDouble},
{"nativeReadString", "(J)Ljava/lang/String;", (void*)android_os_Parcel_readString},
{"nativeReadStrongBinder", "(J)Landroid/os/IBinder;", (void*)android_os_Parcel_readStrongBinder},
{"nativeReadFileDescriptor", "(J)Ljava/io/FileDescriptor;", (void*)android_os_Parcel_readFileDescriptor},
@@ -765,7 +782,8 @@
{"nativeMarshall", "(J)[B", (void*)android_os_Parcel_marshall},
{"nativeUnmarshall", "(J[BII)J", (void*)android_os_Parcel_unmarshall},
{"nativeAppendFrom", "(JJII)J", (void*)android_os_Parcel_appendFrom},
- {"nativeHasFileDescriptors", "!(J)Z", (void*)android_os_Parcel_hasFileDescriptors},
+ // @FastNative
+ {"nativeHasFileDescriptors", "(J)Z", (void*)android_os_Parcel_hasFileDescriptors},
{"nativeWriteInterfaceToken", "(JLjava/lang/String;)V", (void*)android_os_Parcel_writeInterfaceToken},
{"nativeEnforceInterface", "(JLjava/lang/String;)V", (void*)android_os_Parcel_enforceInterface},
diff --git a/core/tests/benchmarks/src/android/os/ParcelBenchmark.java b/core/tests/benchmarks/src/android/os/ParcelBenchmark.java
index 4bd2d00..6c45ae8 100644
--- a/core/tests/benchmarks/src/android/os/ParcelBenchmark.java
+++ b/core/tests/benchmarks/src/android/os/ParcelBenchmark.java
@@ -20,12 +20,15 @@
import com.google.caliper.BeforeExperiment;
public class ParcelBenchmark {
+ private static final int INNER_REPS = 1000;
private Parcel mParcel;
@BeforeExperiment
protected void setUp() {
mParcel = Parcel.obtain();
+ mParcel.setDataPosition(0);
+ mParcel.setDataCapacity(INNER_REPS * 8);
}
@AfterExperiment
@@ -36,43 +39,58 @@
public void timeWriteByte(int reps) {
final byte val = 0xF;
- for (int i = 0; i < reps; i++) {
- mParcel.writeByte(val);
+ for (int i = 0; i < (reps / INNER_REPS); i++) {
+ mParcel.setDataPosition(0);
+ for (int j = 0; j < INNER_REPS; j++) {
+ mParcel.writeByte(val);
+ }
}
}
public void timeReadByte(int reps) {
- mParcel.setDataCapacity(reps);
- for (int i = 0; i < reps; i++) {
- mParcel.readByte();
+ for (int i = 0; i < (reps / INNER_REPS); i++) {
+ mParcel.setDataPosition(0);
+ for (int j = 0; j < INNER_REPS; j++) {
+ mParcel.readByte();
+ }
}
}
public void timeWriteInt(int reps) {
final int val = 0xF;
- for (int i = 0; i < reps; i++) {
- mParcel.writeInt(val);
+ for (int i = 0; i < (reps / INNER_REPS); i++) {
+ mParcel.setDataPosition(0);
+ for (int j = 0; j < INNER_REPS; j++) {
+ mParcel.writeInt(val);
+ }
}
}
public void timeReadInt(int reps) {
- mParcel.setDataCapacity(reps << 2);
- for (int i = 0; i < reps; i++) {
- mParcel.readInt();
+ for (int i = 0; i < (reps / INNER_REPS); i++) {
+ mParcel.setDataPosition(0);
+ for (int j = 0; j < INNER_REPS; j++) {
+ mParcel.readInt();
+ }
}
}
public void timeWriteLong(int reps) {
final long val = 0xF;
- for (int i = 0; i < reps; i++) {
- mParcel.writeLong(val);
+ for (int i = 0; i < (reps / INNER_REPS); i++) {
+ mParcel.setDataPosition(0);
+ for (int j = 0; j < INNER_REPS; j++) {
+ mParcel.writeLong(val);
+ }
}
}
public void timeReadLong(int reps) {
- mParcel.setDataCapacity(reps << 3);
- for (int i = 0; i < reps; i++) {
- mParcel.readLong();
+ for (int i = 0; i < (reps / INNER_REPS); i++) {
+ mParcel.setDataPosition(0);
+ for (int j = 0; j < INNER_REPS; j++) {
+ mParcel.readLong();
+ }
}
}
}