`
CshBBrain
  • 浏览: 643051 次
  • 性别: Icon_minigender_1
  • 来自: 成都
博客专栏
B7d9bf34-126e-301f-819e-81f2615b5a2a
开源WebSocket服务...
浏览量:143153
Group-logo
HTML5移动开发
浏览量:136507
社区版块
存档分类
最新评论

Direct Buffer vs. Heap Buffer

NIO 
阅读更多

 

下面的内容有些从网上搜罗的,有些属于自己总结的,总之就是给使用NIO buffer的童鞋点参考。

1、 劣势:创建和释放Direct Buffer的代价比Heap Buffer得要高;

 

2、 区别:Direct Buffer不是分配在堆上的,它不被GC直接管理(但Direct BufferJAVA对象是归GC管理的,只要GC回收了它的JAVA对象,操作系统才会释放Direct Buffer所申请的空间),它似乎给人感觉是“内核缓冲区(buffer in kernel)”。Heap Buffer则是分配在堆上的,或者我们可以简单理解为Heap Buffer就是byte[]数组的一种封装形式,查看JAVA源代码实现,Heap Buffer也的确是这样。

 

3、 优势:当我们把一个Direct Buffer写入Channel的时候,就好比是“内核缓冲区”的内容直接写入了Channel,这样显然快了,减少了数据拷贝(因为我们平时的read/write都是需要在I/O设备与应用程序空间之间的“内核缓冲区”中转一下的)。而当我们把一个Heap Buffer写入Channel的时候,实际上底层实现会先构建一个临时的Direct Buffer,然后把Heap Buffer的内容复制到这个临时的Direct Buffer上,再把这个Direct Buffer写出去。当然,如果我们多次调用write方法,把一个Heap Buffer写入Channel,底层实现可以重复使用临时的Direct Buffer,这样不至于因为频繁地创建和销毁Direct Buffer影响性能。

 

简单的说,我们需要牢记三点:

(1) 平时的read/write,都会在I/O设备与应用程序空间之间经历一个“内核缓冲区”。

(2) Direct Buffer就好比是“内核缓冲区”上的缓存,不直接受GC管理;而Heap Buffer就仅仅是byte[]字节数组的包装形式。因此把一个Direct Buffer写入一个Channel的速度要比把一个Heap Buffer写入一个Channel的速度要快。

(3) Direct Buffer创建和销毁的代价很高,所以要用在尽可能重用的地方。

 


E文参考REFER:

http://stackoverflow.com/questions/5670862/bytebuffer-allocate-vs-bytebuffer-allocatedirect 

Operating systems perform I/O operations on memory areas. These memory areas, as far as the operating system is concerned, are contiguous sequences of bytes. It's no surprise then that only byte buffers are eligible to participate in I/O operations. Also recall that the operating system will directly access the address space of the process, in this case the JVM process, to transfer the data. This means that memory areas that are targets of I/O perations must be contiguous sequences of bytes. In the JVM, an array of bytes may not be stored contiguously in memory, or the Garbage Collector could move it at any time. Arrays are objects in Java, and the way data is stored inside that object could vary from one JVM implementation to another.

For this reason, the notion of a direct buffer was introduced. 

Direct buffers are intended for interaction with channels and native I/O routines. They make a best effort to store the byte elements in a memory area that a channel can use for direct, or raw, access by using native code to tell the operating system to drain or fill the memory area directly.

Direct byte buffers are usually the best choice for I/O operations. By design, they support the most efficient I/O mechanism available to the JVM. Nondirect byte buffers can be passed to channels, but doing so may incur a performance penalty. It's usually not possible for a nondirect buffer to be the target of a native I/O operation. If you pass a nondirect ByteBuffer object to a channel for write, the channel may implicitly do the following on each call:

1. Create a temporary direct ByteBuffer object.

2. Copy the content of the nondirect buffer to the temporary buffer.

3. Perform the low-level I/O operation using the temporary buffer.

4. The temporary buffer object goes out of scope and is eventually garbage collected.

This can potentially result in buffer copying and object churn on every I/O, which are exactly the sorts of things we'd like to avoid. However, depending on the implementation, things may not be this bad. The runtime will likely cache and reuse direct buffers or perform other clever tricks to boost throughput. 

If you're simply creating a buffer for one-time use, the difference is not significant. 

如果我们构造一个ByteBuffer仅仅使用一次,不复用它,那么Direct Buffer和Heap Buffer没有明显的区别。两个地方我们可能通过Direct Buffer来提高性能:

1、 大文件,尽管我们Direct Buffer只用一次,但是如果内容很大,Heap Buffer的复制代价会很高,此时用Direct Buffer能提高性能。这就是为什么,当我们下载一个大文件时,服务端除了用SendFile机制,也可以用“内存映射”,把大文件映射到内存,也就是MappedByteBuffer,是一种Direct Buffer,然后把这个MappedByteBuffer直接写入SocketChannel,这样减少了数据复制,从而提高了性能。

 

2、 重复使用的数据,比如HTTP的错误信息,例如404呀,这些信息是每次请求,响应数据都一样的,那么我们可以把这些固定的信息预先存放在Direct Buffer中(当然部分修改Direct Buffer中的信息也可以,重要的是Direct Buffer要能被重复使用),这样把Direct Buffer直接写入SocketChannel就比写入Heap Buffer要快了。

On the other hand, if you will be using the buffer repeatedly in a high-performance scenario, you're better off allocating direct buffers and reusing them.

Direct buffers are optimal for I/O, but they may be more expensive to create than nondirect byte buffers.

The memory used by direct buffers is allocated by calling through to native, operating system-specific code, bypassing the standard JVM heap. Setting up and tearing down direct buffers could be significantly more expensive than heap-resident buffers, depending on the host operating system and JVM implementation. The memory-storage areas of direct buffers are not subject to garbage collection because they are outside the standard JVM heap.

The performance tradeoffs of using direct versus nondirect buffers can vary widely by JVM, operating system, and code design. By allocating memory outside the heap, you may subject your application to additional forces of which the JVM is unaware. When bringing additional moving parts into play, make sure that you're achieving the desired effect. I recommend the old software maxim: first make it work, then make it fast. Don't worry too much about optimization up front; concentrate first on correctness. The JVM implementation may be able to perform buffer caching or other optimizations that will give you the performance you need without a lot of unnecessary effort on your part.

分享到:
评论

相关推荐

    java 中Buffer源码的分析

    Buffer 是 Java 中一个非常重要的知识点,Direct Buffer 和 Heap Buffer 是两种不同的 Buffer,Direct Buffer 可以提高效率和减少GC 的频率,而 Heap Buffer 需要进行数据复制,因此效率较低。在实际开发中,应该...

    系统稳定性——OutOfMemoryError常见原因及解决方法1

    1. Java heap space 2. GC overhead limit exceeded 3. Permgen space 5. Unable to c

    缓冲池 java

    Buffer分为两种类型:Heap Buffer和Direct Buffer。Heap Buffer存储在Java堆中,而Direct Buffer存储在系统内存中,直接与硬件交互,减少了Java虚拟机(JVM)的内存拷贝,提高了性能。然而,Direct Buffer可能会占用...

    java代码-buffer

    Java NIO提供了两种Buffer类型:Heap Buffer和Direct Buffer。Heap Buffer在Java堆内存中创建,而Direct Buffer在操作系统堆外内存中创建,减少了系统调用的开销,适用于大容量数据传输。 6. **实战应用** - 文件...

    深入理解计算机系统(英文版)

    2.2.7 Advice onSigned vs.Unsigned . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52 2.3 Integer Arithmetic . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53 ...

    JAVA常见错误(方便开发人员查找问题,也方便测试人员对bug进行描述)

    8. java.lang.OutOfMemoryError:Direct buffer memory 该错误是由于Direct buffer memory的溢出。解决方法是调整-XX:MaxDirectMemorySize=参数。 9. java.lang.ArithmeticException 该错误是当出现异常的运算条件...

    Java中的缓冲区(直接缓冲区、非直接缓冲区等).docx

    ByteBuffer directBuffer = ByteBuffer.allocateDirect(1024); ``` 2. **非直接缓冲区**: 非直接缓冲区是在Java堆中分配的,数据传输需要经过JVM堆。虽然它没有直接缓冲区那么高效,但在处理小数据量时,由于...

    教你分析9种OOM常见原因及解决方案.docx

    8. Java.lang.OutOfMemoryError: Direct Buffer 错误 * 原因分析:直接缓冲区的内存不足 * 解决方案:增加直接缓冲区的内存大小、检查直接缓冲区的使用情况、优化直接缓冲区的使用 9. Java.lang.OutOfMemoryError:...

    理论:第十三章:堆溢出,栈溢出的出现场景以及解决方案.docx

    3. OutOfMemoryError: Direct buffer memory:堆外内存。 4. OutOfMemoryError: unable to create new native thread:无法创建新 native 线程。 解决方案: * 通过 -XX:MaxMetaspaceSize=512m 等 JVM 参数调整 ...

    netty-code源码

    7. **零拷贝(Zero-Copy)**:Netty通过DirectBuffer和FileRegion实现零拷贝技术,减少了数据在内存中的复制,提高了性能。 8. **ChannelFuture和Promise**:ChannelFuture表示异步操作的结果,而Promise则用于设置...

    Netty权威指南 (第2版)

    - 内存管理:DirectBuffer与HeapBuffer的选择 - 零拷贝技术:FileRegion和ByteBuf的使用 - 线程模型优化:EventLoopGroup的配置 - 长连接管理:心跳检测和超时策略 6. **Netty实战应用** - 构建Web服务器和...

    Java内存溢出解决办法

    如果直接内存过大,也会导致`java.lang.OutOfMemoryError: Direct buffer memory`。可以通过设置-Dsun.nio.ch maks.directBufferCount和-Djnio-direct-buffer-size来限制直接内存。 解决Java内存溢出问题通常需要...

    老生常谈JVM的内存溢出说明及参数调整

    本文详细讲解了JVM中的内存溢出问题,包括堆栈溢出、PermGen溢出、Direct buffer memory溢出、Stack Overflow溢出和无法创建新native线程溢出五种常见的内存溢出情况,并对每种情况进行了详细的分析和解决方案。...

    使用Direct3D12实施动态资源

    本篇将详细探讨如何利用Direct3D12实现动态资源,特别是通过使用环形缓冲区(Ring Buffer)技术。 动态资源在3D渲染中指的是频繁更新或改变的数据,如顶点、索引缓冲区以及纹理数据。这些资源需要高效地在GPU之间...

    Netty 35道面试题和答案.docx

    Netty是一个高性能、异步事件...HeapBuffer由JVM管理,适用于数据量较小的情况。Selector的register方法用于向选择器注册通道并设置监听事件,SelectionKey代表了注册关系,wakeup方法用于唤醒被阻塞的Selector线程。

    netty各种例子(基于netty各种例子。).zip

    7. **内存管理**:Netty通过DirectBuffer和HeapBuffer实现了高效的内存管理,减少了不必要的系统调用。 8. **流式API**:Netty的API设计为流式,使得编写处理流程更加直观。 9. **错误处理**:Netty提供了优雅的...

    netty 4.1.22.Final中文版的api chm版本的

    3. **内存管理**:Netty采用零拷贝技术,如直接缓冲区(DirectBuffer)和堆外内存(Off-Heap Memory),提高了数据传输效率。 4. **高效的数据编码和解码**:Netty的ByteBuf作为字节缓冲区,提供了方便的读写操作,...

    无私奉献-jvm面试备战

    OutOfMemoryError 异常有多种场景,包括 java.lang.OutOfMemoryError: Java heap space、java.lang.OutOfMemoryError: GC overhead limit exceeded 和 java.lang.OutOfMemoryError: Direct buffer memory 等。

    Netty面试专题.zip

    - **Direct Buffer和Heap Buffer**:Netty支持直接内存和堆内存,直接内存避免了JVM和操作系统之间的数据拷贝,提高性能。 - **FileRegion**:用于传输文件,实现零拷贝,减少了内存与磁盘之间的数据复制。 5. **...

Global site tag (gtag.js) - Google Analytics