什么是直接内存与非直接内存

根据官方文档的描述:

A byte buffer is either direct or non-direct. Given a direct byte buffer, the Java virtual machine will make a best effort to perform native I/O operations directly upon it. That is, it will attempt to avoid copying the buffer's content to (or from) an intermediate buffer before (or after) each invocation of one of the underlying operating system's native I/O operations.

byte byffer可以是两种类型,一种是基于直接内存(也就是非堆内存);另一种是非直接内存(也就是堆内存)。

对于直接内存来说,JVM将会在IO操作上具有更高的性能,因为它直接作用于本地系统的IO操作。而非直接内存,也就是堆内存中的数据,如果要作IO操作,会先复制到直接内存,再利用本地IO处理。

从数据流的角度,非直接内存是下面这样的作用链:

本地IO-->直接内存-->非直接内存-->直接内存-->本地IO

而直接内存是:

本地IO-->直接内存-->本地IO

很明显,再做IO处理时,比如网络发送大量数据时,直接内存会具有更高的效率。

A direct byte buffer may be created by invoking the allocateDirect factory method of this class. The buffers returned by this method typically have somewhat higher allocation and deallocation costs than non-direct buffers. The contents of direct buffers may reside outside of the normal garbage-collected heap, and so their impact upon the memory footprint of an application might not be obvious. It is therefore recommended that direct buffers be allocated primarily for large, long-lived buffers that are subject to the underlying system's native I/O operations. In general it is best to allocate direct buffers only when they yield a measureable gain in program performance.

但是,不要高兴的太早。文档中也说了,直接内存使用allocateDirect创建,但是它比申请普通的堆内存需要耗费更高的性能。不过,这部分的数据是在JVM之外的,因此它不会占用应用的内存。

所以呢,当你有很大的数据要缓存,并且它的生命周期又很长,那么就比较适合使用直接内存。只是一般来说,如果不是能带来很明显的性能提升,还是推荐直接使用堆内存。

关于直接内存需要注意的,就是上面两点了,其他的关于视图啊、作用链啊,都是使用上的问题了。如果有兴趣,可以参考官方API ( 进去后搜索ByteBuffer,就能看到!),里面有少量的描述!重要的一些用法,还得自己摸索。

使用场景

通过上面的官方文档,与一些资料的搜索。可以总结下,直接内存的使用场景:

  • 1 有很大的数据需要存储,它的生命周期又很长
  • 2 适合频繁的IO操作,比如网络并发场景

申请分配地址速度比较

下面用一段简单的代码,测试下申请内存空间的速度:

int time = 10000000;
Date begin = new Date();
for(int i=0;i<time;i++){ByteBuffer buffer = ByteBuffer.allocate(2);
}
Date end = new Date();
System.out.println(end.getTime()-begin.getTime());
begin = new Date();
for(int i=0;i<time;i++){ByteBuffer buffer = ByteBuffer.allocateDirect(2);
}
end = new Date();
System.out.println(end.getTime()-begin.getTime());

得到的测试结果如下:

在数据量提升时,直接内存相比于非直接内存的申请 有十分十分十分明显的性能问题!

读写速度比较

然后在写段代码,测试下读写的速度:

int time = 1000;
Date begin = new Date();
ByteBuffer buffer = ByteBuffer.allocate(2*time);
for(int i=0;i<time;i++){buffer.putChar('a');
}
buffer.flip();
for(int i=0;i<time;i++){buffer.getChar();
}
Date end = new Date();
System.out.println(end.getTime()-begin.getTime());
begin = new Date();
ByteBuffer buffer2 = ByteBuffer.allocateDirect(2*time);
for(int i=0;i<time;i++){buffer2.putChar('a');
}
buffer2.flip();
for(int i=0;i<time;i++){buffer2.getChar();
}
end = new Date();
System.out.println(end.getTime()-begin.getTime());

测试的结果如下:

可以看到直接内存在直接的IO操作上,还是有明显的差异的!

作者:xingoo

出处:http://www.cnblogs.com/xing901022

from:https://www.cnblogs.com/xing901022/p/5243657.html

Java直接内存与非直接内存性能测试相关推荐

  1. JVM堆内存与非堆内存(heap)官方详解

    JVM堆内存与非堆内存(heap)官方详解 JAVA堆内存管理是影响性能主要因素之一. 堆内存溢出是JAVA项目非常常见的故障,在解决该问题之前,必须先了解下JAVA堆内存是怎么工作的. 先看下JAV ...

  2. C# 托管内存与非托管内存之间的转换

    C# 托管内存与非托管内存之间的转换 c#有自己的内存回收机制,所以在c#中我们可以只new,不用关心怎样delete,c#使用gc来清理内存,这部分内存就是managed memory,大部分时候我 ...

  3. 转 C# 托管内存与非托管内存之间的转换

    1.c#的托管代码和非托管代码 c#有自己的内存回收机制,所以在c#中我们可以只new,不用关心怎样delete,c#使用gc来清理内存,这部分内存就是managed memory,大部分时候我们工作 ...

  4. java堆和非堆_java 堆与非堆 内存

    堆(Heap)和非堆(Non-heap)内存 按照官方的说法:"Java 虚拟机具有一个堆,堆是运行时数据区域,所有类实例和数组的内存均从此处分配.堆是在 Java 虚拟机启动时创建的.&q ...

  5. Java堆内存Heap与非堆内存Non-Heap简介和设置

    Java 开发对JVM(Java虚拟机)的了解很有必要,网上看到,收集整理转载一下,方便日后的懒人计划 堆(Heap)和非堆(Non-heap)内存 按照官方的说法:"Java 虚拟机具有一 ...

  6. Java堆内存Heap与非堆内存Non-Heap

    堆(Heap)和非堆(Non-heap)内存     按照官方的说法:"Java 虚拟机具有一个堆,堆是运行时数据区域,所有类实例和数组的内存均从此处分配.堆是在 Java 虚拟机启动时创建 ...

  7. java non-heap_Java堆内存Heap与非堆内存Non-Heap简介和设置

    Java 开发对JVM(Java虚拟机)的了解很有必要,网上看到,收集整理转载一下,方便日后的懒人计划 堆(Heap)和非堆(Non-heap)内存 按照官方的说法:"Java 虚拟机具有一 ...

  8. bat java 指定堆大小_jvm 堆内存 栈内存 大小设置 查看堆大小

    1.在eclipse设置JVM参数 打开eclipse-窗口-首选项-Java-已安装的JRE(对在当前开发环境中运行的java程序皆生效,也就是在eclipse中运行的java程序)编辑当前使用的J ...

  9. java 64位 默认分配内存大小_JVM默认内存大小

    堆(Heap)和非堆(Non-heap)内存 按照官方的说法:"Java虚拟机具有一个堆,堆是运行时数据区域,所有类实例和数组的内存均从此处分配.堆是在Java虚拟机启动时创建的." ...

最新文章

  1. LeetCode 300. Longest Increasing Subsequence--O(n log n)--Java,C++,Python解法
  2. nginx配置参数详解
  3. SQL Server 2008_企业版和开发版产品密钥
  4. struts.xml 文件添加DTD文件
  5. PHP获取数组最后一个值的2种方法
  6. Facebook开源计算机视觉目标检测平台Detectron
  7. xp怎样安装android-studio,Xposed 框架的安装
  8. 为什么要监控sql语句,以及如何监控,都有哪几种方式可以监控。
  9. windows 使用qtcreater编译boost 测试
  10. windows下SBT的安装与使用
  11. 如何把proe的工作目录怎么设置在服务器上的唯一方法
  12. java js对象转字符串数组_js 转json格式的字符串为对象或数组(前后台)的方法
  13. 有计算机科学与技术专业的大学,开设计算机科学与技术专业的大学有哪些,开设计算机科学与技术专业的大学有哪些...
  14. docker创建mysql实例_使用docker创建mysql实例
  15. mysql数据排序问题
  16. G1垃圾回收器总结一
  17. [常微分方程的数值解法系列一] 常微分方程
  18. 1023组成最小数(20分) - 用不到20行代码破解20分的题目
  19. JavaSE基础知识
  20. 北航计算机学院王华峰,计算机前沿科学与技术分论坛第二场宣讲会

热门文章

  1. mmTrix大数据分析平台构建实录--转
  2. 详解 Spring 3.0 基于 Annotation 的依赖注入实现--转载
  3. struts深入原理之RequestProcessor与xml
  4. 数据挖掘建模之常见概率分布总结
  5. 没用过这些 IDEA 插件?怪不得写代码头疼
  6. 以太坊联合创始人发明了新语言叫板Vyper,主链之后语言将引领新一轮大战?...
  7. 卷积神经网络的网络结构——以LeNet-5为例
  8. 专访友盟CEO叶谦:深挖海量终端用户数据的价值
  9. 小工匠聊架构文章一览【不间断持续更新】
  10. Spring-注入参数详解-[通过util命名空间简化集合类型的配置]