直接内存和堆内存谁快

前言

直接内存大多时候也被称为堆外内存,自从 JDK 引入 NIO 后,直接内存的使用也越来越普遍。通过 native 方法可以分配堆外内存,通过 DirectByteBuffer 对象来操作。

直接内存不属于 Java 堆,所以它不受堆大小限制,但是它受物理内存大小的限制。

配置

可以通过 -XX:MaxDirectMemorySize 参数来设置最大可用直接内存,如果启动时未设置则默认为最大堆内存大小,即与 -Xmx 相同。即假如最大堆内存为1G,则默认直接内存也为1G,那么 JVM 最大需要的内存大小为2G多一些。当直接内存达到最大限制时就会触发GC,如果回收失败则会引起OutOfMemoryError。

分配内存耗时

环境为JDK9,两种内存分配的耗时如下,运行两遍让其预热。可以看到直接内存的分配比较耗时,而堆内存分配操作耗时少好几倍。

public static void directMemoryAllocate() {
		long tsStart = System.currentTimeMillis();
		for (int i = 0; i < 100000; i++) {
			ByteBuffer buffer = ByteBuffer.allocateDirect(400);

		}
		System.out.println("direct memory allocate: " + (System.currentTimeMillis() - tsStart) + " ms");
		tsStart = System.currentTimeMillis();
		for (int i = 0; i < 100000; i++) {
			ByteBuffer buffer = ByteBuffer.allocate(400);
		}
		System.out.println("heap memory allocate: " + (System.currentTimeMillis() - tsStart) + " ms");
	}
direct memory allocate: 149 ms
heap memory allocate: 41 ms
direct memory allocate: 122 ms
heap memory allocate: 31 ms

读写操作耗时

环境为JDK9,两种内存的读写操作耗时如下,同样运行两遍让其预热,可以看到直接内存读写操作的速度相对快一些。

public static void memoryRW() {
		ByteBuffer buffer = ByteBuffer.allocateDirect(400);
		ByteBuffer buffer2 = ByteBuffer.allocate(400);
		long tsStart = System.currentTimeMillis();
		for (int i = 0; i < 100000; i++) {
			for (int j = 0; j < 100; j++) {
				buffer.putInt(j);
			}
			buffer.flip();
			for (byte j = 0; j < 100; j++) {
				buffer.getInt();
			}
			buffer.clear();
		}
		System.out.println("direct memory rw: " + (System.currentTimeMillis() - tsStart) + " ms");

		tsStart = System.currentTimeMillis();
		for (int i = 0; i < 100000; i++) {
			for (int j = 0; j < 100; j++) {
				buffer2.putInt(j);
			}
			buffer2.flip();
			for (byte j = 0; j < 100; j++) {
				buffer2.getInt();
			}
			buffer2.clear();
		}
		System.out.println("heap memory rw: " + (System.currentTimeMillis() - tsStart) + " ms");
	}
direct memory rw: 39 ms
heap memory rw: 34 ms
direct memory rw: 23 ms
heap memory rw: 46 ms

总结

理论上直接内存的机制访问速度要快一些,但也不能武断地直接说直接内存快,另外,在内存分配操作上直接内存要慢一些。直接内存更适合在内存申请次数较少,但读写操作较频繁的场景。

-------------推荐阅读------------

我的2017文章汇总——机器学习篇

我的2017文章汇总——Java及中间件

我的2017文章汇总——深度学习篇

我的2017文章汇总——JDK源码篇

我的2017文章汇总——自然语言处理篇

我的2017文章汇总——Java并发篇


跟我交流,向我提问:

这里写图片描述

公众号的菜单已分为“读书总结”、“分布式”、“机器学习”、“深度学习”、“NLP”、“Java深度”、“Java并发核心”、“JDK源码”、“Tomcat内核”等,可能有一款适合你的胃口。

为什么写《Tomcat内核设计剖析》

欢迎关注:

这里写图片描述

猜你喜欢

转载自juejin.im/post/5b0def9ef265da0908442207