2019独角兽企业重金招聘Python工程师标准>>>

Which one is faster: Java heap or native memory?

11-29-2012 by  Sergio Oliveira Jr.  |  8 Comments

One of the advantages of the Java language is that you do not need to deal with memory allocation and deallocation. Whenever you instantiate an object with the new keyword, the necessary memory is allocated in the JVM heap. The heap is then managed by the garbate collector which reclaims the memory after the object goes out-of-scope. However there is a backdoor to reach the off-heap native memory from the JVM. In this article I am going to show how an object can be stored in memory as a sequence of bytes and how you can choose between storing these bytes in heap memory or in direct (i.e. native) memory. Then I will try to conclude which one is faster to access from the JVM: heap memory or direct memory.

Allocating and Deallocating with Unsafe

The sun.misc.Unsafe class allows you to allocate and deallocate native memory from Java like you were calling malloc andfree from C. The memory you create goes off the heap and are not managed by the garbage collector so it becomes your responsibility to deallocate the memory after you are done with it. Here is my Direct utility class to gain access to the Unsafeclass.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
publicclassDirectimplementsMemory {
privatestaticUnsafe unsafe;
privatestaticbooleanAVAILABLE =false;
static{
try{
Field field = Unsafe.class.getDeclaredField("theUnsafe");
field.setAccessible(true);
unsafe = (Unsafe)field.get(null);
AVAILABLE =true;
}catch(Exception e) {
// NOOP: throw exception later when allocating memory
}
}
publicstaticbooleanisAvailable() {
returnAVAILABLE;
}
privatestaticDirect INSTANCE =null;
publicstaticMemory getInstance() {
if(INSTANCE ==null) {
INSTANCE =newDirect();
}
returnINSTANCE;
}
privateDirect() {
}
@Override
publiclongalloc(longsize) {
if(!AVAILABLE) {
thrownewIllegalStateException("sun.misc.Unsafe is not accessible!");
}
returnunsafe.allocateMemory(size);
}
@Override
publicvoidfree(longaddress) {
unsafe.freeMemory(address);
}
@Override
publicfinallonggetLong(longaddress) {
returnunsafe.getLong(address);
}
@Override
publicfinalvoidputLong(longaddress,longvalue) {
unsafe.putLong(address, value);
}
@Override
publicfinalintgetInt(longaddress) {
returnunsafe.getInt(address);
}
@Override
publicfinalvoidputInt(longaddress,intvalue) {
unsafe.putInt(address, value);
}
}

Placing an object in native memory

Let’s move the following Java object to native memory:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
publicclassSomeObject {
privatelongsomeLong;
privateintsomeInt;
publiclonggetSomeLong() {
returnsomeLong;
}
publicvoidsetSomeLong(longsomeLong) {
this.someLong = someLong;
}
publicintgetSomeInt() {
returnsomeInt;
}
publicvoidsetSomeInt(intsomeInt) {
this.someInt = someInt;
}
}

Note that all we are doing below is saving its properties in the Memory:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
publicclassSomeMemoryObject {
privatefinalstaticintsomeLong_OFFSET =0;
privatefinalstaticintsomeInt_OFFSET =8;
privatefinalstaticintSIZE =8+4;// one long + one int
privatelongaddress;
privatefinalMemory memory;
publicSomeMemoryObject(Memory memory) {
this.memory = memory;
this.address = memory.alloc(SIZE);
}
@Override
publicvoidfinalize() {
memory.free(address);
}
publicfinalvoidsetSomeLong(longsomeLong) {
memory.putLong(address + someLong_OFFSET, someLong);
}
publicfinallonggetSomeLong() {
returnmemory.getLong(address + someLong_OFFSET);
}
publicfinalvoidsetSomeInt(intsomeInt) {
memory.putInt(address + someInt_OFFSET, someInt);
}
publicfinalintgetSomeInt() {
returnmemory.getInt(address + someInt_OFFSET);
}
}

Now let’s benchmark read/write access for two arrays: one with millions of SomeObjects and another one with millions ofSomeMemoryObjects. The code can be seen here and the results are below:

// with JIT:
Number of Objects:  1,000     1,000,000     10,000,000    60,000,000
Heap Avg Write:      107         2.30          2.51         2.58
Native Avg Write:    305         6.65          5.94         5.26
Heap Avg Read:       61          0.31          0.28         0.28
Native Avg Read:     309         3.50          2.96         2.16
// without JIT: (-Xint)
Number of Objects:  1,000     1,000,000     10,000,000    60,000,000
Heap Avg Write:      104         107           105         102
Native Avg Write:    292         293           300         297
Heap Avg Read:       59          63            60          58
Native Avg Read:     297         298           302         299

Conclusion: Crossing the JVM barrier to reach native memory is approximately 10 times slower for reads and 2 times slower for writes. But notice that each SomeMemoryObject is allocating its own native memory space so the reads and writes are not continuous, in other words, each direct memory object reads and writes from and to its own allocated memory space that can be located anywhere. Let’s benchmark read/write access to continuous direct and heap memory to try to determine which one is faster.

Accessing large chunks of continuous memory

The test consist of allocating a byte array in the heap and a corresponding chunk of native memory to hold the same amount of data. Then we sequentially write and read a couple of times to measure which one is faster. We also test random access to any location of the array and compare the results. The sequential test can be seen here. The random one can be seenhere. The results:

// with JIT and sequential access:
Number of Objects:  1,000     1,000,000     1,000,000,000
Heap Avg Write:      12          0.34           0.35
Native Avg Write:    102         0.71           0.69
Heap Avg Read:       12          0.29           0.28
Native Avg Read:     110         0.32           0.32
// without JIT and sequential access: (-Xint)
Number of Objects:  1,000     1,000,000      10,000,000
Heap Avg Write:      8           8              8
Native Avg Write:    91          92             94
Heap Avg Read:       10          10             10
Native Avg Read:     91          90             94
// with JIT and random access:
Number of Objects:  1,000     1,000,000     1,000,000,000
Heap Avg Write:      61          1.01           1.12
Native Avg Write:    151         0.89           0.90
Heap Avg Read:       59          0.89           0.92
Native Avg Read:     156         0.78           0.84
// without JIT and random access: (-Xint)
Number of Objects:  1,000     1,000,000      10,000,000
Heap Avg Write:      55          55              55
Native Avg Write:    141         142             140
Heap Avg Read:       55          55              55
Native Avg Read:     138         140             138

Conclusion: Heap memory is always faster than direct memory for sequential access. For random access, heap memory is a little bit slower for big chunks of data, but not much.

Final Conclusion

Working with Native memory from Java has its usages such as when you need to work with large amounts of data (> 2 gigabytes) or when you want to escape from the garbage collector [1]. However in terms of latency, direct memory access from the JVM is not faster than accessing the heap as demonstrated above. The results actually make sense since crossing the JVM barrier must have a cost. That’s the same dilema between using a direct or a heap ByteBuffer. The speed advantage of the direct ByteBuffer is not access speed but the ability to talk directly with the operating system’s native I/O operations. Another great example discussed by Peter Lawrey is the use of memory-mapped files when working with time-series.

转载于:https://my.oschina.net/fourthmoon/blog/116146

Which one is faster: Java heap or native memory?相关推荐

  1. java heap buffer direct buffer_java NIO - DirectBuffer 和 HeapBuffer

    问题 : DirectBuffer 属于堆外存,那应该还是属于用户内存,而不是内核内存? FileChannel 的read(ByteBuffer dst)函数,write(ByteBuffer sr ...

  2. java native堆_Java Native Memory比堆更快吗?

    执行IO时,直接内存更快,因为它可以避免一个数据副本.但是,对于95%的申请,您不会注意到差异. 您可以将数据存储在直接内存中,但是它不会比存储数据POJO快. (或安全,可读或可维护)如果您担心GC ...

  3. 应用jacob组件造成的内存溢出解决方案(java.lang.OutOfMemoryError: Java heap space)

    http://www.educity.cn/wenda/351088.html 使用jacob组件造成的内存溢出解决方案(java.lang.OutOfMemoryError: Java heap s ...

  4. 分布式应用,response导出error on submit request on future invoke、java.lang.OutOfMemoryError: Java heap space

    背景 HSF 分布式框架 ,基于EasyExcel 实现excel导出 . 控制层, GET请求 , 传递 HttpServletRequest 和 HttpServletRespose 到,业务中台 ...

  5. jetty java heap space_JFinal + HTTL + jdk1.7 启动服务内存溢出,Java heap space 但jdk1.6正常...

    eclispe  开发 JFinal + HTTL  + jdk1.6 发布都正常, 今天服务器升级了jdk1.7, 本地也装了jdk1.7测试 编译后用jetty 启动 都会报错,一下内存就溢出了, ...

  6. 【原创】-eclipse下连Hadoop报java.lang.OutOfMemoryError: Java heap space的解决办法

    eclipse下java.lang.OutOfMemoryError: Java heap space的解决办法: 一.在eclipse下远程连接Hadoop出现如下问题: 14/03/28 22:3 ...

  7. JVM Heap Memory和Native Memory

    JVM管理的内存可以总体划分为两部分:Heap Memory和Native Memory.前者我们比较熟悉,是供Java应用程序使用的:后者也称为C-Heap,是供JVM自身进程使用的.Heap Me ...

  8. java heap 内存_深入理解jvm之内存区域与内存溢出

    Java内存区域与内存溢出异常 运行时数据区域 程序计数器当前线程所执行的字节码的行号指示器 当前线程私有 不会出现OutOfMemoryError情况 java虚拟机栈线程私有,生命周期与线程相同 ...

  9. Android—Java层与Native层对象的关联

    JNI 函数注册 静态注册: 1.java层的native方法, 如:public native void close(); 2.头文件:JNIEXPORT void JNICALL Java_and ...

最新文章

  1. Java学习之for语句
  2. Spring - 父容器与子容器
  3. Word转换英文为大写小写的方法
  4. 偶遇mysql(Percona Server)的一个新bug
  5. 微信小程序之坦克大战学习
  6. DiscuzX系列命令执行分析公开(三连弹)
  7. ANSI C typedef
  8. VMware虚拟机下安装CentOS 6.10并配置访问外网
  9. Barcode for Mac(条形码生成器)
  10. java敏感词过滤_java敏感词过滤
  11. java中的创建和调用_如何在Mirth Connect中创建和调用自定义Java代码
  12. windows存储空间清理,C盘空间清理教程,磁盘清理方法
  13. Rayson API 框架分析系列之1: 简介
  14. zookeeper-选举流程
  15. Spark Streaming背压机制
  16. Could not enlist in transaction on entering meta-aware object!”
  17. 这是一篇系统的追热点方法论
  18. 视频融合应用没听说过?
  19. Macbook Pro无法使用Logi Option连接蓝牙鼠标解决方法
  20. Unity3D导入SteamVR Plugin后如何运行非VR场景

热门文章

  1. easyui 动态设置单元格控件_插入控件-gt;引用变量-gt;实现动态图表纵横筛选
  2. 【Linux】26.VScode安装、插件、快捷键等基本用法
  3. Caffe代码导读(0):路线图
  4. An overview of gradient descent optimization algorithms
  5. SVM学习(三):线性分类器的求解
  6. 循环神经网络教程4-用Python和Theano实现GRU/LSTM RNN, Part 4 – Implementing a GRU/LSTM RNN with Python and Theano
  7. Apriori算法简介及实现(python)
  8. 深度学习(十六)基于2-channel network的图片相似度判别-CVPR 2015
  9. MATLAB语言中的关系与逻辑运算
  10. 购买阿里云遇到Permission denied的问题