偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

面試題:什么是零拷貝技術(shù)?

開發(fā) 前端
這是一道高頻的面試題,而且在很多技術(shù)中都使用到了,比如javaNIO、kafka、Netty、Linux等等。作為一個(gè)非常重要的知識(shí)點(diǎn),而且又是高頻面試題,有必要從零開始好好地認(rèn)識(shí)一下。

[[387261]]

這是一道高頻的面試題,而且在很多技術(shù)中都使用到了,比如javaNIO、kafka、Netty、Linux等等。作為一個(gè)非常重要的知識(shí)點(diǎn),而且又是高頻面試題,有必要從零開始好好地認(rèn)識(shí)一下。

OK,開始今天的文章。

一、什么是零拷貝?

1、從一個(gè)案例說(shuō)起

為了解釋這個(gè)概念,我們先要從一個(gè)需求說(shuō)起,說(shuō)某天某領(lǐng)導(dǎo)給你下發(fā)了一個(gè)任務(wù),完成一個(gè)從文件中讀取數(shù)據(jù),并傳輸?shù)骄W(wǎng)絡(luò)上的一個(gè)小程序。代碼很簡(jiǎn)單:

首先我們?cè)谖覀兊牟僮飨到y(tǒng)中找到這個(gè)文件,然后把數(shù)據(jù)先讀到緩沖區(qū),最后把緩沖區(qū)的數(shù)據(jù)發(fā)送到網(wǎng)絡(luò)上。

代碼是很簡(jiǎn)單,現(xiàn)在我們考慮一下,這個(gè)數(shù)據(jù)從電腦到網(wǎng)絡(luò)整個(gè)傳輸?shù)倪^(guò)程:

現(xiàn)在我們可以看到1->2->3->4的整個(gè)過(guò)程一共經(jīng)歷了四次拷貝的方式,但是真正消耗資源和浪費(fèi)時(shí)間的是第二次和第三次,因?yàn)檫@兩次都需要經(jīng)過(guò)我們的CPU拷貝,而且還需要內(nèi)核態(tài)和用戶態(tài)之間的來(lái)回切換。想想看,我們的CPU資源是多么寶貴,要處理大量的任務(wù)。還要去拷貝大量的數(shù)據(jù)。如果能把CPU的這兩次拷貝給去除掉,豈不快哉!!!既能節(jié)省CPU資源,還可以避免內(nèi)核態(tài)和用戶態(tài)之間的切換。

這里還要先說(shuō)一下用戶態(tài)和內(nèi)核態(tài)的區(qū)別:

處于用戶態(tài)執(zhí)行時(shí),進(jìn)程所能訪問的內(nèi)存空間和對(duì)象受到限制,其所處于占有的處理器是可被搶占的

處于內(nèi)核態(tài)執(zhí)行時(shí),則能訪問所有的內(nèi)存空間和對(duì)象,且所占有的處理器是不允許被搶占的。

2、優(yōu)化方案

要去除第二次和第三次之間的拷貝,Linux開發(fā)人員也早就注意到了這個(gè)問題,于是在linux 2.1內(nèi)核中,添加了 “數(shù)據(jù)被copy到socket buffer”的動(dòng)作,于是我們的javaNIO,可以直接調(diào)用transferTo()的方法,就可以實(shí)現(xiàn)這種現(xiàn)象。

現(xiàn)在一看,感覺性能資源都得到了很大的提升,不過(guò)現(xiàn)在還不并不是完美的。因?yàn)檫@三次拷貝還用到了CPU的拷貝技術(shù),就是第二次。不過(guò)不要擔(dān)心。Linux開發(fā)人員比我們更加深謀遠(yuǎn)慮。

3、零拷貝優(yōu)化方案

在Linux2.4 內(nèi)核做了優(yōu)化,取而代之的是只包含關(guān)于數(shù)據(jù)的位置和長(zhǎng)度的信息的描述符被追加到了socket buffer 緩沖區(qū)中。DMA引擎直接把數(shù)據(jù)從內(nèi)核緩沖區(qū)傳輸?shù)絽f(xié)議引擎(protocol engine),從而消除了最后一次CPU copy。經(jīng)過(guò)上述過(guò)程,數(shù)據(jù)只經(jīng)過(guò)了2次copy就從磁盤傳送出去了。這個(gè)才是真正的Zero-Copy

注意:這里的零拷貝其實(shí)是根據(jù)內(nèi)核狀態(tài)劃分的,在這里沒有經(jīng)過(guò)CPU的拷貝,數(shù)據(jù)在用戶態(tài)的狀態(tài)下,經(jīng)歷了零次拷貝,所以才叫做零拷貝,但不是說(shuō)不拷貝。

OK?,F(xiàn)在我們已經(jīng)了解了什么是零拷貝技術(shù),下面我們?cè)僬f(shuō)一下那些數(shù)據(jù)結(jié)構(gòu)會(huì)用到零拷貝技術(shù)。

二、哪些地方會(huì)用到零拷貝技術(shù)

1、java的NIO

先說(shuō)java,是因?yàn)橐o下面的netty做鋪墊,在 Java NIO 中的通道(Channel)就相當(dāng)于操作系統(tǒng)的內(nèi)核空間(kernel space)的緩沖區(qū),而緩沖區(qū)(Buffer)對(duì)應(yīng)的相當(dāng)于操作系統(tǒng)的用戶空間(user space)中的用戶緩沖區(qū)(user buffer)。

堆外內(nèi)存(DirectBuffer)在使用后需要應(yīng)用程序手動(dòng)回收,而堆內(nèi)存(HeapBuffer)的數(shù)據(jù)在 GC 時(shí)可能會(huì)被自動(dòng)回收。因此,在使用 HeapBuffer 讀寫數(shù)據(jù)時(shí),為了避免緩沖區(qū)數(shù)據(jù)因?yàn)?GC 而丟失,NIO 會(huì)先把 HeapBuffer 內(nèi)部的數(shù)據(jù)拷貝到一個(gè)臨時(shí)的 DirectBuffer 中的本地內(nèi)存(native memory),這個(gè)拷貝涉及到 sun.misc.Unsafe.copyMemory() 的調(diào)用,背后的實(shí)現(xiàn)原理與 memcpy() 類似。最后,將臨時(shí)生成的 DirectBuffer 內(nèi)部的數(shù)據(jù)的內(nèi)存地址傳給 I/O 調(diào)用函數(shù),這樣就避免了再去訪問 Java 對(duì)象處理 I/O 讀寫。

(1)MappedByteBuffer

MappedByteBuffer 是 NIO 基于內(nèi)存映射(mmap)這種零拷貝方式的提供的一種實(shí)現(xiàn),意思是把一個(gè)文件從 position 位置開始的 size 大小的區(qū)域映射為內(nèi)存映像文件。這樣之添加地址映射,而不進(jìn)行拷貝。

(2)DirectByteBuffer

DirectByteBuffer 的對(duì)象引用位于 Java 內(nèi)存模型的堆里面,JVM 可以對(duì) DirectByteBuffer 的對(duì)象進(jìn)行內(nèi)存分配和回收管理,是 MappedByteBuffer 的具體實(shí)現(xiàn)類。因此同樣具有零拷貝技術(shù)。

(3)FileChannel

FileChannel 定義了 transferFrom() 和 transferTo() 兩個(gè)抽象方法,它通過(guò)在通道和通道之間建立連接實(shí)現(xiàn)數(shù)據(jù)傳輸?shù)摹?/p>

我們直接看Linux2.4的版本,socket緩沖區(qū)做了調(diào)整,DMA帶收集功能。

(1)DMA從拷貝至內(nèi)核緩沖區(qū)

(2)將數(shù)據(jù)的位置和長(zhǎng)度的信息的描述符增加至內(nèi)核空間(socket緩沖區(qū))

(3)DMA將數(shù)據(jù)從內(nèi)核拷貝至協(xié)議引擎

這個(gè)復(fù)制過(guò)程是零拷貝過(guò)程。

2、Netty

Netty 中的零拷貝和上面提到的操作系統(tǒng)層面上的零拷貝不太一樣, 我們所說(shuō)的 Netty 零拷貝完全是基于(Java 層面)用戶態(tài)的。

(1)Netty 通過(guò) DefaultFileRegion 類對(duì)FileChannel 的 tranferTo() 方法進(jìn)行包裝,相當(dāng)于是間接的通過(guò)java進(jìn)行零拷貝。

(2)我們的數(shù)據(jù)傳輸一般都是通過(guò)TCP/IP協(xié)議實(shí)現(xiàn)的,在實(shí)際應(yīng)用中,很有可能一條完整的消息被分割為多個(gè)數(shù)據(jù)包進(jìn)行網(wǎng)絡(luò)傳輸,而單個(gè)的數(shù)據(jù)包對(duì)你而言是沒有意義的,只有當(dāng)這些數(shù)據(jù)包組成一條完整的消息時(shí)你才能做出正確的處理,而Netty可以通過(guò)零拷貝的方式將這些數(shù)據(jù)包組合成一條完整的消息供你來(lái)使用。

此時(shí)零拷貝的作用范圍僅在用戶空間中。那Netty是如何實(shí)現(xiàn)的呢?為此我們就要找到Netty進(jìn)行數(shù)據(jù)傳輸?shù)慕涌?,這個(gè)接口一定包含了可以實(shí)現(xiàn)零拷貝的功能,這個(gè)接口就是ChannelBuffer。

既然有接口肯定就有實(shí)現(xiàn)類,一個(gè)最主要的實(shí)現(xiàn)類是CompositeChannelBuffer,這個(gè)類的主要作用是將多個(gè)ChannelBuffer組成一個(gè)虛擬的ChannelBuffer來(lái)進(jìn)行操作

為什么說(shuō)是虛擬的呢,因?yàn)镃ompositeChannelBuffer并沒有將多個(gè)ChannelBuffer真正的組合起來(lái),而只是保存了他們的引用,這樣就避免了數(shù)據(jù)的拷貝,實(shí)現(xiàn)了Zero Copy。

(3)ByteBuf 可以通過(guò) wrap 操作把字節(jié)數(shù)組、ByteBuf、ByteBuffer 包裝成一個(gè) ByteBuf 對(duì)象, 進(jìn)而避免了拷貝操作

(4)ByteBuf 支持 slice 操作, 因此可以將 ByteBuf 分解為多個(gè)共享同一個(gè)存儲(chǔ)區(qū)域的 ByteBuf,避免了內(nèi)存的拷貝

3、kafka

Kafka 的索引文件使用的是 mmap + write 方式,數(shù)據(jù)文件使用的是 sendfile 方式。適用于系統(tǒng)日志消息這種高吞吐量的大塊文件的數(shù)據(jù)持久化和傳輸。

如果有10個(gè)消費(fèi)者,傳統(tǒng)方式下,數(shù)據(jù)復(fù)制次數(shù)為4*10=40次,而使用“零拷貝技術(shù)”只需要1+10=11次,一次為從磁盤復(fù)制到頁(yè)面緩存,10次表示10個(gè)消費(fèi)者各自讀取一次頁(yè)面緩存。

OK,先到這里。

本文轉(zhuǎn)載自微信公眾號(hào)「愚公要移山」,可以通過(guò)以下二維碼關(guān)注。轉(zhuǎn)載本文請(qǐng)聯(lián)系愚公要移山公眾號(hào)。

 

責(zé)任編輯:武曉燕 來(lái)源: 愚公要移山
相關(guān)推薦

2023-07-29 13:45:30

了不起 Java極

2024-06-24 00:09:00

零拷貝技術(shù)MMapsendFile

2010-12-29 10:33:51

Oracle

2022-05-16 08:22:37

零拷貝Netty

2024-06-07 08:10:14

Netty操作系統(tǒng)零拷貝

2020-06-04 14:40:40

面試題Vue前端

2025-10-11 02:11:00

Spring零拷貝磁盤

2024-12-04 14:45:14

零拷貝技術(shù)CPU 拷貝Zero-copy

2022-05-05 13:57:43

Buffer設(shè)備MYSQL

2011-03-24 13:27:37

SQL

2023-08-26 21:42:08

零拷貝I/O操作

2023-11-13 07:37:36

JS面試題線程

2023-07-27 08:26:36

零拷貝I/O操作

2013-11-01 09:27:48

Twitter技術(shù)面試

2009-04-17 09:40:04

微軟技術(shù)中心面試

2015-09-02 09:32:56

java線程面試

2014-09-19 11:17:48

面試題

2024-07-24 08:38:07

2012-08-22 09:32:54

面試面試題

2009-06-06 18:34:05

java面試題
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)