java 堆和直接内存的区别
NIO 的 Buffer 提供了一个可以不经过 JVM 内存直接访问系统物理内存的类——DirectBuffer。
DirectBuffer 类继承自 ByteBuffer,但和普通的 ByteBuffer 不同,普通的 ByteBuffer 仍在 JVM 堆上分配内存,其最大内存受到最大堆内存的限制;而 DirectBuffer 直接分配在物理内存中,并不占用堆空间,其可申请的最大内存受操作系统限制。
直接内存的读写操作比普通 Buffer 快,但它的创建、销毁比普通 Buffer 慢。
因此直接内存使用于需要大内存空间且频繁访问的场合,不适用于频繁申请释放内存的场合。
class DirectMemory {
// 分配堆内存
public static void bufferAccess() {
long startTime = System.currentTimeMillis();
ByteBuffer b = ByteBuffer.allocate(500);
for (int i = 0; i < 1000000; i++) {
for (int j = 0; j < 99; j++)
b.putInt(j);
b.flip();
for (int j = 0; j < 99; j++)
b.getInt();
b.clear();
}
long endTime = System.currentTimeMillis();
System.out.println("access_nondirect:" + (endTime - startTime));
}
// 直接分配内存
public static void directAccess() {
long startTime = System.currentTimeMillis();
ByteBuffer b = ByteBuffer.allocateDirect(500);
for (int i = 0; i < 1000000; i++) {
for (int j = 0; j < 99; j++)
b.putInt(j);
b.flip();
for (int j = 0; j < 99; j++)
b.getInt();
b.clear();
}
long endTime = System.currentTimeMillis();
System.out.println("access_direct:" + (endTime - startTime));
}
public static void bufferAllocate() {
long startTime = System.currentTimeMillis();
for (int i = 0; i < 1000000; i++) {
ByteBuffer.allocate(1000);
}
long endTime = System.currentTimeMillis();
System.out.println("allocate_nondirect:" + (endTime - startTime));
}
public static void directAllocate() {
long startTime = System.currentTimeMillis();
for (int i = 0; i < 1000000; i++) {
ByteBuffer.allocateDirect(1000);
}
long endTime = System.currentTimeMillis();
System.out.println("allocate_direct:" + (endTime - startTime));
}
public static void main(String args[]) {
System.out.println("访问性能测试:");
bufferAccess();
directAccess();
System.out.println();
System.out.println("分配性能测试:");
bufferAllocate();
directAllocate();
}
}
结果:
访问性能测试:
access_nondirect:157
access_direct:134
分配性能测试:
allocate_nondirect:231
allocate_direct:613