Java直接内存与非直接内存性能测试

本文涉及的产品
性能测试 PTS,5000VUM额度
简介:

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

根据官方文档的描述:

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的博客,原文链接:Java直接内存与非直接内存性能测试,如需转载请自行联系原博主。
相关实践学习
通过性能测试PTS对云服务器ECS进行规格选择与性能压测
本文为您介绍如何利用性能测试PTS对云服务器ECS进行规格选择与性能压测。
相关文章
|
11天前
|
缓存 算法 Java
Java中的内存管理:理解与优化
【10月更文挑战第6天】 在Java编程中,内存管理是一个至关重要的主题。本文将深入探讨Java内存模型及其垃圾回收机制,并分享一些优化内存使用的策略和最佳实践。通过掌握这些知识,您可以提高Java应用的性能和稳定性。
36 4
|
11天前
|
存储 监控 算法
Java中的内存管理:理解Garbage Collection机制
本文将深入探讨Java编程语言中的内存管理,着重介绍垃圾回收(Garbage Collection, GC)机制。通过阐述GC的工作原理、常见算法及其在Java中的应用,帮助读者提高程序的性能和稳定性。我们将从基本原理出发,逐步深入到调优实践,为开发者提供一套系统的理解和优化Java应用中内存管理的方法。
|
15天前
|
Java 流计算
Flink-03 Flink Java 3分钟上手 Stream 给 Flink-02 DataStreamSource Socket写一个测试的工具!
Flink-03 Flink Java 3分钟上手 Stream 给 Flink-02 DataStreamSource Socket写一个测试的工具!
31 1
Flink-03 Flink Java 3分钟上手 Stream 给 Flink-02 DataStreamSource Socket写一个测试的工具!
|
2天前
|
存储 人工智能 Java
将 Spring AI 与 LLM 结合使用以生成 Java 测试
AIDocumentLibraryChat 项目通过 GitHub URL 为指定的 Java 类生成测试代码,支持 granite-code 和 deepseek-coder-v2 模型。项目包括控制器、服务和配置,能处理源代码解析、依赖加载及测试代码生成,旨在评估 LLM 对开发测试的支持能力。
9 1
|
4天前
|
存储 监控 算法
Java中的内存管理与垃圾回收机制解析
本文深入探讨了Java编程语言中的内存管理方式,特别是垃圾回收机制。我们将了解Java的自动内存管理是如何工作的,它如何帮助开发者避免常见的内存泄漏问题。通过分析不同垃圾回收算法(如标记-清除、复制和标记-整理)以及JVM如何选择合适的垃圾回收策略,本文旨在帮助Java开发者更好地理解和优化应用程序的性能。
|
6天前
|
存储 Java
Java内存模型
【10月更文挑战第11天】Java 内存模型(JMM)是 Java 虚拟机规范中定义的多线程内存访问机制,解决内存可见性、原子性和有序性问题。它定义了主内存和工作内存的概念,以及可见性、原子性和有序性的规则,确保多线程环境下的数据一致性和操作正确性。使用 `synchronized` 和 `volatile` 等同步机制可有效避免数据竞争和不一致问题。
16 3
|
6天前
|
缓存 安全 Java
使用 Java 内存模型解决多线程中的数据竞争问题
【10月更文挑战第11天】在 Java 多线程编程中,数据竞争是一个常见问题。通过使用 `synchronized` 关键字、`volatile` 关键字、原子类、显式锁、避免共享可变数据、合理设计数据结构、遵循线程安全原则和使用线程池等方法,可以有效解决数据竞争问题,确保程序的正确性和稳定性。
13 2
|
9天前
|
Java 数据挖掘 数据库连接
Java使用直接内存的好处
综上所述,Java直接内存的使用为开发者提供了一种绕过JVM堆限制、直接高效操作内存资源的途径,特别适用于高吞吐量、低延迟和大规模数据处理的场景。虽然直接内存的使用需要更精细的管理以避免内存泄漏和过度消耗系统资源,但恰当的利用能够显著提升应用的性能表现,是现代高性能Java应用不可或缺的工具之一。
10 2
|
10天前
|
Java 数据挖掘 数据库连接
Java使用直接内存的好处
综上所述,Java直接内存的使用为开发者提供了一种绕过JVM堆限制、直接高效操作内存资源的途径,特别适用于高吞吐量、低延迟和大规模数据处理的场景。虽然直接内存的使用需要更精细的管理以避免内存泄漏和过度消耗系统资源,但恰当的利用能够显著提升应用的性能表现,是现代高性能Java应用不可或缺的工具之一。
27 1
|
15天前
|
监控 算法 Java
Java中的内存管理:理解垃圾回收机制
【10月更文挑战第2天】 在本文中,我们将深入探讨Java编程语言中的内存管理机制,特别是垃圾回收机制。我们将从基本原理、垃圾回收算法到实际应用场景全面解析,帮助你更好地理解和优化Java应用的内存使用。无论你是初学者还是有经验的开发者,这篇文章都能带给你新的启发和思考。
26 2