0%

java | 直接内存

Direct Memory 直接内存。

直接内存并不属于 jvm 内存,属于操作系统内存。所以图中没有。

  • 常见于 NIO 操作时,用于数据缓冲区
  • 分配回收成本高,但读写性能强
  • 不受 JVM 内存回收管理

copy 速度的比较

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
package com.redisc;

import lombok.extern.slf4j.Slf4j;

import java.io.*;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;

@Slf4j(topic = "c.Run")
public class Run {

static final String FROM = "";
static final String TO = "";
static final int _1MB = 1024 * 1024;

public static void main(String[] args) throws IOException {
io(); // 传统 IO
directionBuffer(); // 直接内存IO
}

private static void directionBuffer() {
long start = System.nanoTime();
try (FileChannel from = new FileInputStream(FROM).getChannel();
FileChannel to = new FileOutputStream(TO).getChannel();) {
ByteBuffer bb = ByteBuffer.allocateDirect(_1MB);
while (true) {
int len = from.read(bb);
if (len == -1) {
break;
}
bb.flip();
to.write(bb);
bb.clear();
}
} catch (IOException e) {
e.printStackTrace();
}
long end = System.nanoTime();
System.out.println("direct 用时" + (end - start) / 1000000);
}

private static void io() {
long start = System.nanoTime();
try (FileInputStream from = new FileInputStream(FROM);
FileOutputStream to = new FileOutputStream(TO);) {
byte[] buf = new byte[_1MB];
while (true) {
int len = from.read(buf);
if (len == -1) {
break;
}
to.write(buf);
}
} catch (IOException e) {
e.printStackTrace();
}
long end = System.nanoTime();
System.out.println("io 用时" + (end - start) / 1000000);
}

}

ByteBufferbyte 快 好几倍。

原理

  • java 本身不具备磁盘读写能力,如果要调用的话,会根据本地方法区来调用系统指令
    • 图中 CPU
  • 切换到内核态之后,读取磁盘文件
  • 操作系统内存中划出缓冲区,然后把内容逐一读到缓冲区
  • 操作系统的缓冲区,java 并不能直接读取,所以,划出 byte[] 用来接收缓冲区的内容
  • 然后内核态,变为用户态,进行读写
  • 反复这个过程

direct memory 会分配一块直接内存。ByteBuffer.allocateDirect(_1MB);,这块内存,系统可以直接访问,java 代码也可以直接访问。

请我喝杯咖啡吧~