全部產品
Search
文件中心

Alibaba Cloud Linux:代碼多副本功能

更新時間:Jul 17, 2024

在NUMA架構(尤其是ARM執行個體)中,不同NUMA節點具有各自的本地記憶體,當一個NUMA節點上的程式或進程需要訪問其他NUMA節點的程式碼片段時,就會引入額外的延遲和效能開銷。通過代碼多副本功能,可以將遠程節點的程式碼片段複製到本地節點,避免了跨節點訪問,從而解決NUMA架構中因跨節點訪問帶來的效能延遲問題。

背景資訊

  • 什麼是程式碼片段跨節點訪問?對系統有什麼影響?

    • 什麼是程式碼片段跨節點訪問?

      非統一記憶體訪問NUMA (Non-Uniform Memory Access) 是一種電腦架構設計,用於處理多處理器系統中的記憶體訪問延遲和頻寬不均勻的問題。不同的處理器核心和記憶體子系統整體被稱為節點(node),每個節點都有自己的本地記憶體。當一個進程在NUMA架構中運行時,可能由於記憶體不足或Server Load Balancer等原因,作業系統會將記憶體配置在其他節點上。當應用程式或進程需要訪問的程式碼片段儲存在另一個NUMA節點上時,就需要通過跨節點訪問的方式來擷取程式碼片段中的指令。

    • 對系統有什麼影響?

      跨節點存取碼段可能會產生一些效能問題,例如增加訪問延遲、降低執行效率和增加記憶體頻寬的佔用等。這是由於跨節點訪問需要通過匯流排或互連網絡傳輸資料,並在遠程節點上進行記憶體訪問,這些操作通常比本地記憶體訪問更慢,所以要儘可能避免應用跨節點訪問。

  • 代碼多副本功能解決程式碼片段跨節點訪問的技術原理

    代碼多副本的核心作用是當發現應用程式或進程跨節點存取碼段時,在當前節點上建立待存取碼段的副本,這樣可以在本地節點上存取碼段,而無需進行跨節點訪問,從而減少跨節點訪問帶來的延遲和開銷。如下圖所示:

    1. node 1上的Process 1進程跨節點訪問node 0上的libc.so程式碼片段,或者node 0上的Process 0進程跨節點訪問node 1上的test程式碼片段。

    2. 此時通過代碼多副本功能,會在node 1上建立libc.so副本,在node 0上建立test副本。

    3. 那麼Process 1進程實際訪問的是libc.so副本,Process 0進程實際訪問的是test副本,從而消除跨節點訪存。

    說明

    核心以頁(4 KB大小)為粒度管理記憶體,一個程式的程式碼片段可能放在一個或多個記憶體頁中。一個程式的程式碼片段第一次被從硬碟讀入到記憶體,加入到Page Cache(檔案快取)中,所在的記憶體頁叫首頁。如果核心發現某個程式訪問了遠端節點上的程式碼片段,就會把這些程式碼片段以頁為粒度在本地節點上拷貝一份,那麼本地程式碼片段的頁就叫副頁。

    image

使用限制

僅以下執行個體規格和鏡像支援代碼多副本功能。

  • 執行個體規格:ECS Bare Metal Instance規格類型系列群。更多資訊,請參見ECS Bare Metal Instance

  • 鏡像:核心版本是5.10.112-11及以上的Alibaba Cloud Linux 3鏡像。

    說明

    您可以通過uname -r命令查詢鏡像的核心版本。

配置開關

代碼多副本提供了全域開關和memcg開關,只有當兩個開關同時開啟時,核心系統內的進程才能使用代碼多副本功能。

配置開關

說明

/sys/kernel/mm/duptext/enabled

全域開關用於設定當前核心系統是否啟用代碼多副本功能。取值範圍:0~1,預設值為0。

  • 取值為1,表示允許啟用代碼多副本功能。

  • 取值為0,表示禁用或關閉代碼多副本功能。

    說明

    關閉代碼多副本功能時,核心會自動清除整機上的所有副頁。

/sys/fs/cgroup/memory/<memcg目錄名稱>/memory.allow_duptext

在全域開關開啟的前提下,memcg開關用於設定各memcg中的進程是否啟用代碼多副本功能。取值範圍:0~1,預設值為0。

  • 取值為1,表示當前memcg中的進程啟用代碼多副本功能。

  • 取值為0,表示當前memcg中的進程不啟用代碼多副本功能。

說明

除了上述特性開關之外,您還可以通過以下方式查看副頁的統計資料。

  • 通過/proc/vmstat中的nr_duptext欄位或者/proc/meminfo中的DupText欄位查看整機的副頁統計資料。

    • nr_duptext表示在核心中標記為duptext的副頁數量。

    • DupText表示使用了多少記憶體來儲存duptext相關的資料,單位為KB。通常1個記憶體頁的大小是4 KB。

  • 通過/proc/pid/smaps檔案可以查看對應進程的副頁統計資料。

使用代碼多副本功能

本樣本通過在一台具有兩個NUMA節點的ECS執行個體上編譯並執行一個測試程式test.c為例,示範代碼多副本功能的用法。

  1. 遠程登入ECS執行個體。

    具體操作,請參見通過密碼或密鑰認證登入Linux執行個體

  2. (可選)運行以下命令,查看ECS執行個體的NUMA節點資訊。

    numactl -H
    說明

    如果您沒有安裝numactl,可執行sudo yum install numactl命令進行安裝。

    如下圖所示,表示該執行個體有2個NUMA節點(node 0和node 1)。

    image.png

  3. 運行以下命令,編譯測試程式並產生可執行檔。

    本樣本假設在node 1上編譯test.c的原始碼檔案,並在node 1上產生test檔案的Page Cache。

    numactl -N 1 -m 1 gcc test.c -o test
  4. 運行以下命令,開啟代碼多副本功能的全域開關。

    sudo sh -c 'echo 1 > /sys/kernel/mm/duptext/enabled'
  5. 運行以下命令,建立一個memcg目錄並開啟memcg的多副本功能開關。

    sudo mkdir /sys/fs/cgroup/memory/test
    sudo sh -c 'echo 1 > /sys/fs/cgroup/memory/test/memory.allow_duptext'
  6. 運行以下命令,通過代碼多副本功能避免跨節點訪問。

    本樣本假設使用cgexec和numactl來運行可執行檔test,同時將進程綁定到node 0上。此時會在node 0上建立test相關程式碼片段的副本,即直接存取的是node 0上的副本,避免了跨節點訪問。

    sudo cgexec -g "memory:test" numactl -N 0 -m 0 ./test
    說明

    如果您沒有安裝cgexec,可執行sudo yum install -y libcgroup-tools命令進行安裝。

  7. 運行以下命令,查看test程式的副頁統計資料。

    sudo cat /proc/$(pidof test)/smaps

    如下圖所示,展示了test的副頁統計資訊,表示在node 0上已經成功產生了test的副本。

    image.png

    說明

    您也可以分別運行以下命令,查看整機的副頁統計資料。

    cat /proc/vmstat | grep -i duptext
    cat /proc/meminfo | grep -i duptext

關閉代碼多副本功能

後續您可以根據需要關閉代碼多副本功能。關閉多副本功能的同時,核心會自動清除整機上的所有副頁。

  1. 遠程登入ECS執行個體。

    具體操作,請參見通過密碼或密鑰認證登入Linux執行個體

  2. 運行以下命令,關閉代碼多副本功能。

    sudo sh -c 'echo 0 > /sys/kernel/mm/duptext/enabled'
  3. 運行以下命令,驗證是否關閉代碼多副本功能。

    cat /proc/vmstat | grep -i duptext
    cat /proc/meminfo | grep -i duptext

    如下圖所示,整機上的所有副頁已經被清除,表示已經關閉代碼多副本功能。

    image.png