共用方式為


從 Linux 用戶端存取大型目錄時最佳化檔案共用效能

本文提供了處理包含大量檔案的目錄的建議。 通常,透過將檔案分散到多個目錄中來減少單一目錄中的檔案數是一種很好的做法。 不過,在某些情況下,大型目錄是無法避免的。 在 Linux 用戶端上掛接的 Azure 檔案共用上處理大型目錄時,請考慮以下建議。

適用於

管理模型 計費模型 媒體分層 冗餘性 SMB NFS
Microsoft 儲存服務 已佈建的 v2 SSD (進階版) 本地 (LRS) 否 是的
Microsoft 儲存服務 已佈建的 v2 SSD (進階版) 區域 (ZRS) 否 是的
Microsoft 儲存服務 已佈建的 v2 HDD (標準) 本地 (LRS) 否 否
Microsoft 儲存服務 已佈建的 v2 HDD (標準) 區域 (ZRS) 否 否
Microsoft 儲存服務 已佈建的 v2 HDD (標準) 異地 (GRS) 否 否
Microsoft 儲存服務 已佈建的 v2 HDD (標準) GeoZone (GZRS) 否 否
Microsoft 儲存服務 已佈建的 v1 SSD (進階版) 本地 (LRS) 否 是的
Microsoft 儲存服務 已佈建的 v1 SSD (進階版) 區域 (ZRS) 否 是的
Microsoft 儲存服務 隨用隨付 HDD (標準) 本地 (LRS) 否 否
Microsoft 儲存服務 隨用隨付 HDD (標準) 區域 (ZRS) 否 否
Microsoft 儲存服務 隨用隨付 HDD (標準) 異地 (GRS) 否 否
Microsoft 儲存服務 隨用隨付 HDD (標準) GeoZone (GZRS) 否 否

增加雜湊貯體的數目

執行列舉的系統上存在的 RAM 總數會影響 NFS 和 SMB 等檔案系統協定的內部運作。 即使使用者沒有遇到高記憶體使用量的情況,但可用的記憶體數量也會影響系統所擁有的 inode 雜湊貯體數目,進而影響/提升大型目錄的列舉效能。 您可以修改系統所擁有的 inode 雜湊貯體數目,以減少在大型列舉工作負載期間可能發生的雜湊衝突。

若要增加 inode 哈希值區的數目,請修改您的開機組態設定:

  1. 使用文字編輯器來編輯 /etc/default/grub 檔案。

    sudo vim /etc/default/grub
    
  2. 將下列文字新增至 /etc/default/grub 檔案。 此命令會將 128MB 設定為 inode 哈希表大小,最多增加 128MB 的系統記憶體耗用量。

    GRUB_CMDLINE_LINUX="ihash_entries=16777216"
    

    如果 GRUB_CMDLINE_LINUX 已經存在,請新增 ihash_entries=16777216 並以空格分隔,如下所示:

    GRUB_CMDLINE_LINUX="<previous commands> ihash_entries=16777216"
    
  3. 若要套用變更,請執行:

    sudo update-grub2
    
  4. 重新啟動系統:

    sudo reboot
    
  5. 若要確認變更在重新啟動後是否有效,請檢查核心 Cmdline 命令:

    cat /proc/cmdline
    

    如果 ihash_entries 是可見的,則表示系統已套用該設定,而且列舉效能應該會以指數級增加的方式提升。

    您也可以檢查 dmesg 輸出,以查看是否套用了核心 Cmdline:

    dmesg | grep "Inode-cache hash table"
    Inode-cache hash table entries: 16777216 (order: 15, 134217728 bytes, linear)
    

下列掛接選項是列舉特有的選項,可在處理大型目錄時減少延遲。

actimeo

actimeo掛接選項會指定用戶端快取檔案或目錄屬性的時間(以秒為單位),然後用戶端才會向伺服器要求屬性資訊。 在此期間,伺服器上發生的變更會保持未偵測到,直到用戶端再次檢查伺服器為止。 針對SMB客戶端,預設屬性快取逾時設定為1秒。

在 NFS 用戶端上,指定actimeo會將acregminacregmaxacdirminacdirmax全部設定為相同的值。 如果未指定 actimeo,則用戶端會使用每個選項的預設值。

建議您在處理大型目錄時,將 actimeo 設定為 30 到 60 秒之間。 在此範圍內設定值可讓屬性在用戶端的屬性快取中保持更長時間的有效期,以允許作業從快取中取得檔案屬性,而不是透過網路擷取它們。 這可以在作業仍在執行時快取屬性過期的情況下減少延遲。

對於單一目錄中包含 100 萬個檔案的工作負載,下圖比較了使用預設掛接與將 actimeo 值設定為 30 時完成不同作業所需的總時間。 在我們的測試中,某些作業的總完成時間減少了高達 77%。 所有作業都是使用未設定別名的 ls 來執行的。

對於包含 100 萬個檔案的工作負載,此圖表比較了使用預設掛接與將 actimeo 值設為 30 時完成不同作業的時間。

NFS nconnect

NFS nconnect 是 NFS 檔案共用的用戶端掛接選項,可讓您在用戶端與 NFS 檔案共享之間使用多個 TCP 連線。 我們建議採用最佳設定 nconnect=4 來減少延遲並提高效能。 nconnect 功能對於從多個線程使用異步或同步 I/O 的工作負載特別有用。 深入了解

命令和作業

指定命令和作業的方式也會影響效能。 使用 ls 命令來列出大型目錄中的所有檔案是一個很好的範例。

附註

某些作業 (例如遞歸 lsfinddu) 需要檔案名稱和檔案屬性,因此它們會結合使用目錄列舉 (以取得項目) 和每個項目的統計資料 (以取得屬性)。 建議您在可能執行此類命令的掛接點上為 actimeo 使用更高的值。

使用未設定別名的 ls

在某些 Linux 發行版中,殼層會自動為 ls 命令 (例如 ls --color=auto) 設定預設選項。 這會改變 ls 透過網路的運作方式,並將更多作業新增至 ls 執行中。 為了避免效能下降,我們建議使用未設定別名的 ls。 您可以透過以下三種方式之一來執行此動作:

  • 作為只影響目前會話的暫時因應措施,您可以使用 命令 unalias ls來移除別名。

  • 若要進行永久性變更,您可以編輯使用者的 bashrc/bash_aliases 檔案中的 ls 別名。 在 Ubuntu 中,編輯 ~/.bashrc 以移除 ls 的別名。

  • 您可以直接呼叫 ls 二進位檔 (例如 /usr/bin/ls),而不是呼叫 ls。 這樣,您就可以使用 ls,而無需使用別名中可能包含的任何選項。 您可以透過執行命令 which ls 來尋找二進位檔的位置。

防止 ls 對其輸出進行排序

ls 與其他命令一起使用時,如果您不在意 ls 傳回檔案的順序,可以透過阻止 ls 對其輸出進行排序來提高效能。 對輸出進行排序會增加顯著的額外負荷。

您可以將 -f-U 選項與 ls 結合使用來防止輸出被排序,而不是執行 ls -l | wc -l 來取得檔案的總數。 差異在於 -f 也會顯示隱藏的檔案,而且 -U 不會。

例如,如果您在 Ubuntu 中直接呼叫 ls 二進位檔,則應執行 /usr/bin/ls -1f | wc -l/usr/bin/ls -1U | wc -l

以下圖表比較了使用未設定別名且未排序的 ls 與已排序的 ls 輸出結果所需的時間。

此圖表比較了完成已排序 ls 作業與未排序 ls 作業的總時間 (以秒為單位)。

檔案複製和備份作業

從檔案共用複製資料或從檔案共用備份到另一個位置時,為了獲得最佳效能,我們建議使用共用快照作為來源,而不是使用具有作用中 I/O 的即時檔案共用。 備份應用程式應直接在快照上執行命令。 如需詳細資訊,請參閱將共用快照與 Azure 檔案儲存體結合使用

應用程式層級建議

開發使用大型目錄的應用程式時,請遵循這些建議。

  • 略過檔案屬性。 如果應用程式只需要檔名,而不需要檔案類型或上次修改時間等檔案屬性,您可以多次呼叫系統函數,例如 getdents64,使用適當的緩衝區大小來取得指定目錄中無需檔案類型的項目,藉由避免不必要的額外作業來提升操作速度。

  • 交錯執行 stat 呼叫。 如果應用程式需要屬性和檔名,我們建議將 stat 呼叫與 getdents64 交錯執行,而不是先使用 getdents64 取得檔尾的所有項目,然後再對所有傳回的項目執行 statx 動作。 交錯執行 stat 呼叫會指示用戶端同時要求檔案及其屬性,以減少對伺服器的呼叫次數。 當與較高的 actimeo 值結合時,交錯執行 stat 呼叫可以顯著提高效能。 例如,不要使用 [ getdents64, getdents64, ... , getdents64, statx (entry1), ... , statx(n) ],而是將 statx 呼叫放在每個 getdents64 之後,如下所示:[ getdents64, (statx, statx, ... , statx), getdents64, (statx, statx, ... , statx), ... ]

  • 增加 I/O 深度。 如果可能,我們建議將 nconnect 設定為非零值 (大於 1),並將作業分佈在多個執行緒中,或使用非同步 I/O。 這可讓可為非同步的作業受益於檔案共用的多個並行連線。

  • 強制使用快取。 如果應用程式正在查詢只有一台用戶端已掛接的檔案共用上的檔案屬性,請使用具有 AT_STATX_DONT_SYNC 旗標的 statx 系統呼叫。 此旗標可確保會從快取中擷取快取的屬性,而無需與伺服器同步,以避免為獲取最新資料而進行的額外網路往返。

另請參閱