當前位置: 華文世界 > 科技

科大訊飛:說說零拷貝技術和多路復用技術?

2024-09-06科技

零拷貝技術和多路復用技術是現代電腦系統和網絡編程中兩項重要的最佳化手段,旨在提高數據處理和傳輸的效率。如高效能框架 Netty 中,即使用了零拷貝技術又使用了多路復用技術,同時來保證 Netty 框架的高效能執行。

1.零拷貝技術

零拷貝(Zero-copy)技術是一種電腦作業系統中用於提高數據傳輸效率的最佳化策略。在傳統的數據傳輸過程中,需要將數據從一個緩沖區拷貝到另一個緩沖區,然後再傳輸給目標。這涉及到多次的 CPU 和記憶體之間的數據拷貝操作,會消耗 CPU 的時間和記憶體頻寬。而零拷貝技術透過直接共享數據的記憶體地址,避免了中間的拷貝過程,從而提高了數據傳輸的效率。

1.1 傳統IO

要搞明白零拷貝技術就要先搞清楚傳統 IO 的執行流程,傳統的 IO 的執行流程如下:

① 使用者態 VS 內核態

作業系統有使用者態和內核態之分,這是因為電腦體系結構中的作業系統設計了兩個不同的執行環境,以提供不同的功能和特權級別。

  • 使用者態(User Mode) 是指應用程式執行時的執行環境。在使用者態下,應用程式只能存取受限資源,如應用程式自身的記憶體空間、CPU 寄存器等,並且不能直接存取作業系統的底層資源和硬件器材。
  • 內核態(Kernel Mode) 是指作業系統內核執行時的執行環境。在內核態下,作業系統具有更高的許可權,可以直接存取系統的硬件和底層資源,如 CPU、記憶體、器材驅動程式等。
  • ② DMA技術

    DMA(Direct Memory Access,直接記憶體存取)技術,繞過 CPU,直接在記憶體和外設之間進行數據傳輸。這樣可以減少 CPU 的參與,提高數據傳輸的效率。

    1.2 零拷貝技術

    零拷貝技術可以利用 Linux 下的 MMap、sendFile 等手段來實作,使得數據能夠直接從磁盤對映到內核緩沖區,然後透過 DMA 傳輸到網卡緩存,整個過程中 CPU 只負責管理和排程,而無需執行實際的數據復制指令。

    ① MMap

    MMap(Memory Map)是 Linux 作業系統中提供的一種將檔對映到行程地址空間的一種機制,透過 MMap 行程可以像存取記憶體一樣存取檔,而無需顯式的復制操作。

    使用 MMap 可以把 IO 執行流程最佳化成以下執行步驟:

    傳統的 IO 需要四次拷貝和四次上下文(使用者態和內核態)切換,而 MMap 只需要三次拷貝和四次上下文切換,從而能夠提升程式整體的執行效率,並且節省了程式的記憶體空間。

    ② senFile 方法

    在 Linux 作業系統中 sendFile() 是一個系統呼叫函數,用於高效地將檔數據從內核空間直接傳輸到網絡套接字(Socket)上,從而實作零拷貝技術。這個函數的主要目的是減少 CPU 上下文切換以及記憶體復制操作,提高文件傳輸效能。

    使用 sendFile() 可以把 IO 執行流程最佳化成以下執行步驟:

    1.3 零拷貝技術套用

    在 Java 中,以下幾個地方使用了零拷貝技術:

    1. NIO(New I/O)通道 :java.nio.channels.FileChannel 提供了 transferTo() 和 transferFrom() 方法,可以直接將數據從一個通道傳輸到另一個通道,例如從檔通道直接傳輸到 Socket 通道,整個過程無需將數據復制到使用者空間緩沖區,從而實作了零拷貝。
    2. Socket Direct Buffer :在 JDK 1.4 及更高版本中,Java NIO 支持使用直接緩沖區(DirectBuffer),這類緩沖區是在系統堆外分配的,可以直接由網卡硬件進行 DMA 操作,減少數據在使用者態與內核態之間復制次數 ,提高網絡數據發送效率。
    3. Apache Kafka 或者 Netty 等高效能框架 :這些框架在底層實作上通常會利用 Java NIO 的上述特性來最佳化數據傳輸,如 Kafka 生產者和消費者在傳輸訊息時會用到零拷貝技術以提升效能。

    2.多路復用技術

    多路復用技術則是一種讓單個行程(或執行緒)能夠同時監視多個描述符(如檔描述符、socket描述符)的技術,當其中任何一個描述符準備好進行讀、寫或者異常操作時,就會通知該行程。這種方式可以顯著提高並行處理能力,減少系統開銷,特別是在處理大量並行連線時。

    主要的多路復用技術包括:

    1. select :最基礎的多路復用介面,但受限於最大檔描述符數量,且每次呼叫都需要重新傳入所有待檢查的描述符集合。
    2. poll :相對於 select 有所改進,使用連結串列管理描述符,解決了檔描述符數量限制問題,但仍存在效率問題。
    3. epoll :提供了更高效的事件通知機制,僅關註發生變化的檔描述符,避免了無謂的遍歷,特別適用於高並行場景。

    在 Java 中,可以透過 NIO(非阻塞 I/O)庫中的 Selector 實作多路復用,結合諸如 FileChannel.transferTo() 等方法實作零拷貝,從而在開發高效能網絡套用和服務時顯著提升數據處理和傳輸的效率。

    課後思考

    Netty 中使用了哪種零拷貝技術?它的多路復用和 NIO 的多路復用有什麽區別?