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

根据官方文档的描述:

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操作上,还是有明显的差异的!

Java直接内存与非直接内存性能测试的更多相关文章

  1. 【转载】java项目中经常碰到的内存溢出问题: java.lang.OutOfMemoryError: PermGen space, 堆内存和非堆内存,写的很好,理解很方便

    Tomcat Xms Xmx PermSize MaxPermSize 区别 及 java.lang.OutOfMemoryError: PermGen space 解决 解决方案 在 catalin ...

  2. 干货:JVM 堆内存和非堆内存

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

  3. JVM 堆内存和非堆内存

    转载自:http://www.importnew.com/27645.html 堆和非堆内存 按照官方的说法:“Java 虚拟机具有一个堆(Heap),堆是运行时数据区域,所有类实例和数组的内存均从此 ...

  4. Windows内核编程之:分页内存与非分页内存 #define PAGEDCODE code_seg("PAGE") (转)

    原文链接:http://blog.chinaunix.net/uid-24504987-id-161192.html Windows规定有些虚拟内存可以交换到文件中,这类内存被称为分页内存 有些虚拟内 ...

  5. Windows内核编程之:分页内存与非分页内存

    Windows规定有些虚拟内存可以交换到文件中,这类内存被称为分页内存 有些虚拟内存 永远不会交换到文件中,这些内存叫非分页内存 #define PAGEDCODE code_seg(“PAGE”); ...

  6. 如何让IntPtr指向一块内存,以及托管内存与非托管内存的相互转化

    IntPtr idp= IntPtr.Zero; StringBuilder idata = new StringBuilder("000000"); string idata = ...

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

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

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

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

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

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

随机推荐

  1. linux两个线程

    http://blog.csdn.net/marksinoberg/article/details/50945212

  2. Laravel5.4 Oauth2.0认证应用 API 实战!

    项目初始化 新建项目 lukeyans-MacBook-Pro:laravel lukeyan$ laravel new laravel_demo 添加laravel自带的Passport服务 luk ...

  3. [SoapUI] 获取当前时间包括年月日时分秒来作为命名

    import java.text.SimpleDateFormat GregorianCalendar calendar = new GregorianCalendar() def dateForma ...

  4. 01 Maven 安装与配置

    Maven 安装与配置 1. Maven 介绍 Maven 翻译为 "专家","内行".Maven 是 Apache 下的一个纯 Java 开发的开源项目,它是 ...

  5. 1.spring环境的搭建

    1.app.config <?xml version="1.0" encoding="utf-8" ?><configuration> ...

  6. 【Maven】安装及配置(Win)

    Maven Maven是一款自动化构建的工具软件,它是基于项目对象模型(POM),可以通过一小段描述信息来管理项目的构建,报告和文档的软件项目管理工具. 检查环境 maven是基于Java的工具软件, ...

  7. Java知识系列 -- 反射

    原理 要想理解 Java 反射,首先要弄清类的加载过程. 比如这行代码 Person p = new Person();. 我们想要创建一个 Person 对象,并用 p 作为对象的引用. 在 Jav ...

  8. MySQL之练习题5

    .将所有的课程的名称以及对应的任课老师姓名打印出来,如下: SELECT cname,tname FROM course INNER JOIN teacher WHERE course.teacher ...

  9. 使用Java实现网络爬虫

    网络爬虫 网络爬虫(又被称为网页蜘蛛,网络机器人,在FOAF社区中间,更经常的称为网页追逐者),是一种按照一定的规则,自动地抓取万维网信息的程序或者脚本. 另外一些不常使用的名字还有蚂蚁.自动索引.模 ...

  10. flask_数据库

    我们将使用 Flask-SQLAlchemy扩展来管理我们应用程序的数据.这个扩展封装了SQLAlchemy 项目,这是一个 对象关系映射器 或者 ORM.ORMs 允许数据库应用程序与对象一起工作, ...