NIO的Buffer提供了一个可以不经过JVM内存直接访问系统物理内存的类——DirectBuffer。 DirectBuffer类继承自ByteBuffer,但和普通的ByteBuffer不同,普通的ByteBuffer仍在JVM堆上分配内存,其最大内存受到最大堆内存的限制;而DirectBuffer直接分配在物理内存中,并不占用堆空间,其可申请的最大内存受操作系统限制。

直接内存的读写操作比普通Buffer快,但它的创建、销毁比普通Buffer慢(猜测原因是DirectBuffer需向OS申请内存涉及到用户态内核态切换,而后者则直接从堆内存划内存即可)。

因此直接内存使用于需要大内存空间且频繁访问的场合,不适用于频繁申请释放内存的场合。

(Note:DirectBuffer并没有真正向OS申请分配内存,其最终还是通过调用Unsafe的allocateMemory()来进行内存分配。不过JVM对Direct Memory可申请的大小也有限制,可用-XX:MaxDirectMemorySize=1M设置,这部分内存不受JVM垃圾回收管理。)

使用对外内存的原因:

  • 对垃圾回收停顿的改善。由于堆外内存是直接受操作系统管理而不是JVM,所以当我们使用堆外内存时,即可保持较小的堆内内存规模。从而在GC时减少回收停顿对于应用的影响。
  • 提升程序I/O操作的性能。通常在I/O通信过程中,会存在堆内内存到堆外内存的数据拷贝操作,对于需要频繁进行内存间数据拷贝且生命周期较短的暂存数据,都建议存储到堆外内存。

以下是一些测试:

代码:

 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

可见与在JVM堆分配内存(allocate)相比,直接内存分配(allocateDirect)的访问性能更好,但分配较慢。(一般如此,当然数据量小的话差别不是那么明显)

最新文章

  1. cx_Oracle摘记
  2. JavaScript定时器原理分析
  3. CentOS6.8下部署Zabbix3.0
  4. ActiveMQ学习(一)——MQ的基本概念
  5. 只用CSS美化选择框
  6. BZOJ1086 [SCOI2005]王室联邦(树分块)
  7. MySql的安装与使用
  8. HTTP 404 - 未找到文件 怎么样解决
  9. Codeforces 518D Ilya and Escalator
  10. A Byte of Python 笔记(12)python 标准库:sys、os,更多内容
  11. Redis 学习笔记-入门
  12. 常见Linux网卡配置范例
  13. 解决IOS微信浏览器底部会出现向前向后返回按钮,返回不刷新的问题
  14. ubuntu18.04使用sudo时反应时间长
  15. 20135202闫佳歆--week3 构造一个简单的Linux系统MenuOs--学习笔记
  16. Jerasure库简介及使用范例
  17. Git学习(一)(2015年11月12日)
  18. js 数组删除元素,并获得真实长度
  19. 面向对象课程 - 寒假第三次作业 - C++计算器项目初始部分
  20. word2vec 和 doc2vec 词向量表示

热门文章

  1. 微信Swift完整项目应用源码
  2. luke使用
  3. LintCode389.判断数独是否合法
  4. the request resource is not available
  5. MySQL 一致性读 深入研究
  6. 理解Java对象序列化
  7. x86开启 HUGEPAGES
  8. 《使用Hibernate开发租房系统》内部测试笔试题
  9. CentOS 6.5 升级 PHP 到5.6
  10. Linux下Source Insight的安装和汉化