非直接字节缓冲区的get/put是否比直接字节缓冲区更快?
如果我必须从直接字节缓冲区中读取/写入,那么先将其读取/写入到线程本地字节数组中,然后使用字节数组完整地更新(对于写入而言)直接字节缓冲区会更好吗?
非直接字节缓冲区的get/put是否比直接字节缓冲区更快?
如果我必须从直接字节缓冲区中读取/写入,那么先将其读取/写入到线程本地字节数组中,然后使用字节数组完整地更新(对于写入而言)直接字节缓冲区会更好吗?
public static void main(String... args) {
ByteBuffer bb1 = ByteBuffer.allocateDirect(256 * 1024).order(ByteOrder.nativeOrder());
ByteBuffer bb2 = ByteBuffer.allocateDirect(256 * 1024).order(ByteOrder.nativeOrder());
for (int i = 0; i < 10; i++)
runTest(bb1, bb2);
}
private static void runTest(ByteBuffer bb1, ByteBuffer bb2) {
bb1.clear();
bb2.clear();
long start = System.nanoTime();
int count = 0;
while (bb2.remaining() > 0)
bb2.putInt(bb1.getInt());
long time = System.nanoTime() - start;
int operations = bb1.capacity() / 4 * 2;
System.out.printf("Each putInt/getInt took an average of %.1f ns%n", (double) time / operations);
}
打印
Each putInt/getInt took an average of 83.9 ns
Each putInt/getInt took an average of 1.4 ns
Each putInt/getInt took an average of 34.7 ns
Each putInt/getInt took an average of 1.3 ns
Each putInt/getInt took an average of 1.2 ns
Each putInt/getInt took an average of 1.3 ns
Each putInt/getInt took an average of 1.2 ns
Each putInt/getInt took an average of 1.2 ns
Each putInt/getInt took an average of 1.2 ns
Each putInt/getInt took an average of 1.2 ns
我非常确定JNI调用所需的时间超过1.2纳秒。
public static void main(String... args) {
ByteBuffer bb1 = ByteBuffer.allocateDirect(256 * 1024).order(ByteOrder.nativeOrder());
ByteBuffer bb2 = ByteBuffer.allocateDirect(256 * 1024).order(ByteOrder.nativeOrder());
for (int i = 0; i < 10; i++)
runTest(bb1, bb2);
}
private static void runTest(ByteBuffer bb1, ByteBuffer bb2) {
Unsafe unsafe = getTheUnsafe();
long start = System.nanoTime();
long addr1 = ((DirectBuffer) bb1).address();
long addr2 = ((DirectBuffer) bb2).address();
for (int i = 0, len = Math.min(bb1.capacity(), bb2.capacity()); i < len; i += 4)
unsafe.putInt(addr1 + i, unsafe.getInt(addr2 + i));
long time = System.nanoTime() - start;
int operations = bb1.capacity() / 4 * 2;
System.out.printf("Each putInt/getInt took an average of %.1f ns%n", (double) time / operations);
}
public static Unsafe getTheUnsafe() {
try {
Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
theUnsafe.setAccessible(true);
return (Unsafe) theUnsafe.get(null);
} catch (Exception e) {
throw new AssertionError(e);
}
}
打印
Each putInt/getInt took an average of 40.4 ns
Each putInt/getInt took an average of 44.4 ns
Each putInt/getInt took an average of 0.4 ns
Each putInt/getInt took an average of 0.3 ns
Each putInt/getInt took an average of 0.3 ns
Each putInt/getInt took an average of 0.3 ns
Each putInt/getInt took an average of 0.3 ns
Each putInt/getInt took an average of 0.3 ns
Each putInt/getInt took an average of 0.3 ns
Each putInt/getInt took an average of 0.3 ns
native
调用比您对JNI调用的期望要快得多。这种延迟的主要原因可能是L2缓存速度。 ;)get
或put
正在进行JNI调用以读取/写入缓冲区中的数据。还有其他方法可以做到这一点。这两个语句都不与此相矛盾。 - Stephen C
Memory
类,而该类又通过内在函数实现)。(https://android.googlesource.com/platform/art/+/6cff09a873e0179f2a8d28727d4cd2447bd1bf16/compiler/optimizing/intrinsics.cc#180) - user1643723