File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change 466466
467467102、一个对技术有追求的面试官,是怎么深挖网络与IO的面试连环炮的?
468468
469+ 103、Netty的架构原理图能画一下吗,他是如何体现Reactor架构思想的?
470+
471+ 104、能说说你对堆外内存的理解吗?堆外内存的优势在哪里?
472+
473+ 105、JDK是如何对堆外内存进行分配和回收的?会发生堆外内存溢出吗?
474+
475+ [ 106、如果不使用零拷贝技术,普通的IO操作在OS层面是如何执行的?] ( /docs/03/106.md )
476+
477+ [ 107、听说过mmap吗?内存映射技术为什么可以提升IO性能?] ( /docs/03/107.md )
478+
479+ [ 108、零拷贝技术到底是什么,他是如何提升IO性能的?] ( /docs/03/108.md )
480+
469481### 分布式架构
470482
471483### 中间件系统
Original file line number Diff line number Diff line change 1+ # 106、如果不使用零拷贝技术,普通的IO操作在OS层面是如何执行的?
2+
3+ ![ 一个普通IO操作的底层原理] ( images/106/01.png )
4+
5+ ![ IO操作执行流程] ( images/106/02.png )
6+
7+ ``` text
8+ File file = new File("xxx.txt");
9+ RandomAccessFile raf = new RandomAccessFile(file, "rw");
10+
11+ byte[] arr = new byte[(int) file.length()];
12+ # read读取数据,用户态切换内核态
13+ raf.read(arr);
14+
15+
16+ Socket socket = new ServerSocket(8080).accept();
17+ #
18+ socket.getOutputStream().write(arr);
19+ ```
20+
21+ 1 ) 内核态切换到用户态
22+ 使用read读取数据的时候,会有一次用户态到内核态的切换,也就是说从用户角度切换到了内核角度去执行,这个时候基于DMA引擎把磁盘上的数据拷贝到内核缓冲里去;
23+
24+ 2 ) 内核态切换到用户态
25+ 接着会从内核态切换到用户态,基于CPU把内核缓冲里的数据拷贝到用户缓冲区里去
26+
27+ 3 ) 用户态切换到内核态
28+ 接着我们调用了Socket的输出流的write方法,此时会从用户态切换到内核态,同时基于CPU把用户缓冲区里的数据拷贝到Socket缓冲区里去,接着会有一个异步化的过程,
29+
30+ 基于DMA引擎从Socket缓冲区里把数据拷贝到网络协议引擎里发送出去
31+
32+ 4 ) 内核态切换回用户态
33+ 都完成之后,从内核态切换回用户态
34+
35+ 5 ) 总结
36+
37+ 所以说,从本地磁盘读取数据,到通过网络发送出去,用户态和内核态之间,要发生4次切换,这是其一;
38+
39+ 其二,数据从磁盘拿出来过后,一共要经过4次拷贝;
40+
41+ 所以说,这4次切换和4次拷贝,让普通的IO操作都性能较低
Original file line number Diff line number Diff line change 1+ # 107、听说过mmap吗?内存映射技术为什么可以提升IO性能?
2+
3+ ![ 内存映射] ( images/107/01.png )
4+
5+ 把** 一个磁盘文件映射到内存里来** ,然后把映射到内存里来的数据通过socket发送出去
6+
7+
8+ 有一种mmap技术,也就是内存映射,直接将磁盘文件数据映射到内核缓冲区,这个映射的过程是基于DMA引擎拷贝的,
9+
10+ 同时用户缓冲区是跟内核缓冲区共享一块映射数据的,建立共享映射之后,就不需要从内核缓冲区拷贝到用户缓冲区了
11+
12+ 光是这一点,就可以避免一次拷贝了,但是这个过程中还是会用户态切换到内核态去进行映射拷贝,接着再次从内核态切换到用户态,建立用户缓冲区和内核缓冲区的映射
13+
14+ 接着把数据通过Socket发送出去,还是要再次切换到内核态
15+
16+
17+
18+ 接着直接把内核缓冲区里的数据拷贝到Socket缓冲区里去,然后再拷贝到网络协议引擎里,发送出去就可以了,最后切换回用户态
19+
20+
21+
22+ ** 减少一次拷贝** ,但是并不减少切换次数,一共是4次切换,3次拷贝
23+
24+
25+
26+ mmap技术是主要在RocketMQ里来使用的,公众号:狸猫技术窝,《从0开始带你成为消息中间件高手》的专栏,RocketMQ,里面剖析了一下,RocketMQ底层主要就是基于mmap技术来提升了磁盘文件的读写,性能
Original file line number Diff line number Diff line change 1+ # 108、零拷贝技术到底是什么,他是如何提升IO性能的?
2+
3+ ![ 零拷贝原理] ( images/108/01.png )
4+
5+ linux提供了sendfile,也就是零拷贝技术
6+
7+
8+
9+ 在你的代码里面,如果说你基于零拷贝技术来读取磁盘文件,同时把读取到的数据通过Socket发送出去的话,流程如下,Kafka源码,transferFrom和transferTo两个方法,从磁盘上读取文件,把数据通过网络发送出去
10+
11+
12+
13+ 这个零拷贝技术,就是先从用户态切换到内核态,在内核态的状态下,把磁盘上的数据拷贝到内核缓冲区,同时从内核缓冲区拷贝一些offset和length到Socket缓冲区;接着从内核态切换到用户态,从内核缓冲区直接把数据拷贝到网络协议引擎里去
14+
15+
16+
17+ 同时从Socket缓冲区里拷贝一些offset和length到网络协议引擎里去,但是这个offset和length的量很少,几乎可以忽略
18+
19+
20+
21+ 只要2次切换,2次拷贝,就可以了
22+
23+
24+
25+ kafka、tomcat,都是用的零拷贝技术,rocketmq用的是mmap技术,mmap还是要多2次切换和1次拷贝的,在Java代码中如何进行mmap和零拷贝,大家可以去看一看网上的一些资料
26+
27+
28+
29+ 用户态和内核态,用户态空间,内核态空间
You can’t perform that action at this time.
0 commit comments