次の方法で共有


Linux クライアントから大きなディレクトリにアクセスする際のファイル共有のパフォーマンスを最適化する

この記事では、多数のファイルを含むディレクトリの操作に関する推奨事項を示します。 通常は、ファイルを複数のディレクトリに分散させて、1 つのディレクトリ内のファイルの数を減らすのが良い方法です。 ただし、状況によっては大きなディレクトリを回避できないことがあります。 Linux クライアントにマウントされている Azure ファイル共有で大きなディレクトリを操作する場合は、次の推奨事項を検討してください。

適用対象

管理モデル 課金モデル メディア階層 冗長性 中小企業 ネットワークファイルシステム(NFS)
Microsoft.Storage プロビジョニング済み v2 HDD (標準) ローカル (LRS) いいえ いいえ
Microsoft.Storage プロビジョニング済み v2 HDD (標準) ゾーン (ZRS) いいえ いいえ
Microsoft.Storage プロビジョニング済み v2 HDD (標準) ジオ (GRS) いいえ いいえ
Microsoft.Storage プロビジョニング済み v2 HDD (標準) ジオゾーン (GZRS) いいえ いいえ
Microsoft.Storage プロビジョニング済み v1 SSD (プレミアム) ローカル (LRS) いいえ はい
Microsoft.Storage プロビジョニング済み v1 SSD (プレミアム) ゾーン (ZRS) いいえ はい
Microsoft.Storage 従量課金制 HDD (標準) ローカル (LRS) いいえ いいえ
Microsoft.Storage 従量課金制 HDD (標準) ゾーン (ZRS) いいえ いいえ
Microsoft.Storage 従量課金制 HDD (標準) ジオ (GRS) いいえ いいえ
Microsoft.Storage 従量課金制 HDD (標準) ジオゾーン (GZRS) いいえ いいえ

ハッシュ バケットの数を増やす

列挙を行うシステムに存在する RAM の総量は、NFS や SMB など、ファイルシステム プロトコルの内部動作に影響を与えます。 ユーザーのメモリ使用量が多くない場合でも、利用できるメモリの量はシステムの inode ハッシュ バケットの数に影響を与え、それによって大きなディレクトリの列挙のパフォーマンスが影響を受けたり改善したりします。 システムの inode ハッシュ バケットの数を変更して、大きな列挙ワークロードの間に発生する可能性のあるハッシュ競合を減らすことができます。

inode ハッシュ バケットの数を増やすには、ブート構成設定を変更します。

  1. テキスト エディタで、/etc/default/grub ファイルを編集します。

    sudo vim /etc/default/grub
    
  2. /etc/default/grub ファイルに次のテキストを追加します。 このコマンドは、inode ハッシュ テーブル サイズとして 128 MB を設定し、システム メモリの消費量を最大 128 MB 増やします。

    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. 再起動後に変更が有効であることを確認するには、カーネルのコマンドライン コマンドを確認します。

    cat /proc/cmdline
    

    ihash_entries が表示される場合、システムによって設定が適用されていて、列挙のパフォーマンスが指数関数的に向上するはずです。

    dmesg 出力を確認して、カーネル コマンドラインが適用されたかどうかを確認することもできます。

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

次のマウント オプションは列挙に固有のものであり、大きなディレクトリを操作するときの待ち時間を短縮できます。

actimeo

actimeo マウント オプションは、クライアントがファイルまたはディレクトリの属性をキャッシュしてからサーバーに属性情報を要求する時間 (秒単位) を指定します。 この期間中、サーバーで発生した変更は、クライアントがサーバーをもう一度確認するまで検出されません。 SMB クライアントの場合、既定の属性キャッシュ タイムアウトは 1 秒に設定されます。

NFS クライアントでは、 actimeo を指定すると、すべての acregminacregmaxacdirmin、および acdirmax が同じ値に設定されます。 actimeo を指定していない場合、クライアントではこれらの各オプションで既定値が使用されます。

大きなディレクトリを操作するときは、actimeo を 30 から 60 秒に設定することをお勧めします。 この範囲の値を設定すると、属性はクライアントの属性キャッシュ内で長時間有効なままになり、ネットワーク経由でフェッチするのではなく、キャッシュからファイルの属性を取得する操作を使用できます。 これにより、操作がまだ実行されている間にキャッシュされた属性の有効期限が切れる状況での待ち時間を短縮できます。

次のグラフは、1 つのディレクトリに 100 万個のファイルがあるワークロードについて、既定のマウントと actimeo の値を 30 に設定した場合とで、さまざまな操作の完了までにかかる合計時間を比べたものです。 このテストでは、一部の操作で完了までの合計時間が最大 77% 短縮されました。 すべての操作は、別名ではない ls で行われました。

100 万ファイルのワークロードについて、既定のマウントと actimeo の値を 30 に設定した場合とで、さまざまな操作の完了までにかかる時間を比べたグラフ。

NFS nconnect

NFS nconnect は NFS ファイル共有のクライアント側マウント オプションであり、クライアントと NFS ファイル共有の間で複数の TCP 接続を使用できます。 待ち時間を短縮し、パフォーマンスを向上させるための最適な設定である nconnect=4 をお勧めします。 nconnect 機能は、複数のスレッドからの非同期または同期 I/O を使用するワークロードに特に役立ちます。 詳細情報。

コマンドと操作

コマンドと操作を指定する方法も、パフォーマンスに影響する可能性があります。 ls コマンドを使って大きなディレクトリ内のすべてのファイルを一覧表示する場合がよい例です。

再帰的な lsfinddu などの一部の操作では、ファイル名とファイル属性の両方が必要であるため、(エントリを取得するための) ディレクトリの列挙と (属性を取得するための) 各エントリに対する stat が組み合わされます。 このようなコマンドを実行する可能性が高いマウント ポイントでは、actimeo に高い値を使うことをお勧めします。

別名ではない ls を使用する

一部の Linux ディストリビューションでは、シェルによって ls コマンドに ls --color=auto などの既定のオプションが自動的に設定されます。 これにより、ネットワーク上での ls の動作が変更され、ls の実行に追加される操作が増えます。 パフォーマンスの低下を避けるため、別名ではない ls を使うことをお勧めします。 次の 3 つの方法のいずれかでこれを行うことができます。

  • 現在のセッションにのみ影響する一時的な回避策として、コマンド unalias lsを使用してエイリアスを削除できます。

  • 永続的に変更するには、ユーザーの ls ファイルで bashrc/bash_aliases の別名を編集できます。 Ubuntu では、~/.bashrc を編集して、ls の別名を削除します。

  • ls を呼び出す代わりに、ls のバイナリを直接呼び出すことができます (例: /usr/bin/ls)。 これにより、別名に含まれる可能性のあるオプションを使わずに、ls を使用できます。 バイナリの場所は、which ls コマンドを実行して調べることができます。

ls が出力を並べ替えないようにする

ls を他のコマンドと共に使う場合、ls からファイルが返される順序が重要でないときは、ls による出力の並べ替えを無効にして、パフォーマンスを向上させることができます。 出力を並べ替えると、オーバーヘッドが大幅に増加します。

ls -l | wc -l を実行してファイルの合計数を取得する代わりに、-f-U または ls オプションを使うと、出力の並べ替えが行われません。 違いは、 -f には非表示のファイルも表示され、 -U は表示されないということです。

たとえば、Ubuntu で ls のバイナリを直接呼び出す場合は、/usr/bin/ls -1f | wc -l または /usr/bin/ls -1U | wc -l を実行します。

次のグラフは、別名ではなく並べ替えを行わない ls と、並べ替えを行う ls で、結果の出力にかかる時間を比較したものです。

並べ替えを行う ls 操作と行わない操作が完了するまでの合計時間を秒単位で比較したグラフ。

ファイルのコピーとバックアップの操作

ファイル共有から別の場所にデータをコピーまたはバックアップする場合は、パフォーマンスを最適化するため、アクティブな I/O があるライブ ファイル共有ではなく、共有スナップショットをソースとして使用することをお勧めします。 バックアップ アプリケーションでは、スナップショットに対してコマンドを直接実行する必要があります。 詳細については、「Azure Files で共有スナップショットを使用する」を参照してください。

アプリケーション レベルでの推奨事項

大きなディレクトリを使用するアプリケーションを開発する際は、次の推奨事項に従ってください。

  • ファイル属性をスキップします。 アプリケーションがファイル名のみを必要とし、ファイルの種類や最終変更時刻などのファイル属性を必要としない場合は、適切なバッファー サイズの getdents64 などのシステム呼び出しに対して複数の呼び出しを使用して、指定したディレクトリ内のエントリをファイルの種類なしで取得し、不要な追加操作を回避することで操作を高速化できます。

  • stat 呼び出しをインターリーブします。 アプリケーションで属性とファイル名が必要な場合は、getdents64 でファイルの終わりまですべてのエントリを取得した後、返されたすべてのエントリに対して statx を実行するのではなく、stat の呼び出しと getdents64 をインターリーブすることをお勧めします。 stat の呼び出しをインターリーブすると、クライアントはファイルとその属性の両方を一度に要求するよう指示され、サーバーへの呼び出しの数が減ります。 高い actimeo 値と組み合わせると、インターリーブ統計呼び出しによってパフォーマンスが大幅に向上する可能性があります。 たとえば、[ getdents64, getdents64, ... , getdents64, statx (entry1), ... , statx(n) ] の代わりに、getdents64 のように、各 [ getdents64, (statx, statx, ... , statx), getdents64, (statx, statx, ... , statx), ... ] の後に statx の呼び出しを配置します:。

  • I/O の深さを増やします。 可能であれば、nconnect を 0 以外の値 (1 より大きい値) に構成して複数のスレッドに操作を分散させるか、非同期 I/O を使うことをお勧めします。 これにより、非同期にできる操作は、ファイル共有への複数の同時接続の恩恵を受けることができます。

  • キャッシュを強制的に使います。 1 つのクライアントのみがマウントしているファイル共有でファイル属性のクエリを実行するアプリケーションの場合は、AT_STATX_DONT_SYNC フラグを指定して statx システム呼び出しを使います。 このフラグを使うと、キャッシュされた属性がキャッシュから取得され、サーバーと同期されないので、最新のデータを取得するための余分なネットワーク ラウンド トリップがなくなります。

関連項目