.NET を使用したアップロードとダウンロードのパフォーマンス チューニング
アプリケーションが .NET 用 Azure Storage クライアント ライブラリを使ってデータを転送する場合、要求の速度、メモリ使用量、さらには成功または失敗に影響を与える可能性のあるいくつかの要因があります。 データ転送のパフォーマンスと信頼性を最大にするには、アプリが実行される環境に基づいて、クライアント ライブラリ転送オプションを事前に構成することが重要です。
この記事では、データ転送オプションのチューニングに関するいくつかの考慮事項について説明します。このガイダンスは、StorageTransferOptions
をパラメーターとして受け入れるすべての API に適用されます。 クライアント ライブラリを適切にチューニングすると、複数の要求にデータを効率的に分散できるため、操作速度、メモリ使用量、ネットワークの安定性が向上する可能性があります。
StorageTransferOptions でのパフォーマンス チューニング
StorageTransferOptions の値を適切にチューニングすることは、データ転送操作の信頼性の高いパフォーマンスにとって重要です。 ストレージ転送は、この構造体のインスタンスで定義されているプロパティ値に基づいて、複数のサブ転送にパーティション分割されます。 サポートされる最大転送サイズは、操作とサービスのバージョンによって異なるため、ドキュメントを調べて制限を確認してください。 Blob Storage での転送サイズの制限について詳しくは、「BLOB ストレージのスケール ターゲット」をご覧ください。
StorageTransferOptions
の次のプロパティは、アプリのニーズに基づいてチューニングできます。
- InitialTransferSize - 最初の要求のサイズ (バイト単位)
- MaximumConcurrency - 並列で使用できるサブ転送の最大数
- MaximumTransferSize - 転送の最大長 (バイト単位)
Note
StorageTransferOptions
構造体には null 許容値が含まれていますが、クライアント ライブラリでは、指定されていない各個別値については既定値が使われます。 通常、これらの既定値は、データ センター環境でのパフォーマンスは優れていますが、ホーム コンシューマー環境には適していない可能性があります。 StorageTransferOptions
のチューニングが不十分な場合、操作が非常に長くなる可能性があり、要求がタイムアウトすることさえあります。 StorageTransferOptions
の値を事前にテストし、アプリケーションと環境のニーズに基づいてチューニングすることをお勧めします。
InitialTransferSize
InitialTransferSize は、最初の範囲要求のサイズ (バイト単位) です。 HTTP 範囲要求は部分的な要求であり、この場合は InitialTransferSize
によって定義されたサイズです。 このサイズより小さい BLOB は、1 つの要求で転送されます。 このサイズより大きい BLOB は、サイズ MaximumTransferSize
のチャンクで転送され続けます。
MaximumTransferSize
で指定する値により、InitialTransferSize
に対して定義する値は "制限されない" ことに注意してください。 InitialTransferSize
では、操作全体をサブ転送なしで一度に実行するための、最初の要求に対する個別のサイズ制限を定義します。 多くの場合、InitialTransferSize
は、MaximumTransferSize
に対して定義した値より大きくはないにしても、"少なくとも" それと同じ大きさにする必要があります。 データ転送のサイズによっては、このようにすると、転送が 1 つの要求で完了し、複数の要求のオーバーヘッドが回避されるため、パフォーマンスが向上する可能性があります。
状況に最適な値がわからない場合は、MaximumTransferSize
に使われているのと同じ値に InitialTransferSize
を設定するのが安全なオプションです。
Note
BlobClient
オブジェクトを使うと、InitialTransferSize
より小さい BLOB のアップロードは、Put Block ではなく Put Blob を使って実行されます。
MaximumConcurrency
MaximumConcurrency は、並列転送で使用できるワーカーの最大数です。 現在、転送を並列化できるのは非同期操作のみです。 同期操作では、この値は無視され、順番に実行されます。
この値の有効性は、.NET での接続プールの制限次第であり、特定のシナリオでは既定値によってパフォーマンスが制限される可能性があります。 .NET での接続プールの制限について詳しくは、「.NET Framework での接続プールの制限と .NET 用の新しい Azure SDK」をご覧ください。
MaximumTransferSize
MaximumTransferSize は、転送の最大長 (バイト単位) です。 前に説明したように、この値によって InitialTransferSize
が制限されることは "なく"、MaximumTransferSize
より大きくできます。
データ移動の効率性を維持するため、クライアント ライブラリではすべての転送で MaximumTransferSize
値に常に達するとは限りません。 転送サイズでサポートされる最大値は、操作によって異なる場合があります。 たとえば、2019-12-12 以降のサービス バージョンで Put Block 操作を呼び出すブロック BLOB の最大ブロック サイズは 4000 MiB です。 Blob Storage での転送サイズの制限について詳しくは、「BLOB ストレージのスケール ターゲット」の表をご覧ください。
コードの例
クライアント ライブラリの Upload
メソッドと UploadAsync
メソッドには、BlobUploadOptions パラメーターの一部として StorageTransferOptions インスタンスを受け取るオーバーロードが含まれます。 BlobDownloadToOptions パラメーターを使用する DownloadTo
メソッドと DownloadToAsync
メソッドにも、同様のオーバーロードが存在します。
次のコード例では、StorageTransferOptions
インスタンスの値を定義し、これらの構成オプションをパラメーターとして UploadAsync
に渡す方法を示します。 このサンプルで提供される値は、推奨を意図したものではありません。 これらの値を適切にチューニングするには、アプリの特定のニーズを考慮する必要があります。
// Specify the StorageTransferOptions
BlobUploadOptions options = new BlobUploadOptions
{
TransferOptions = new StorageTransferOptions
{
// Set the maximum number of parallel transfer workers
MaximumConcurrency = 2,
// Set the initial transfer length to 8 MiB
InitialTransferSize = 8 * 1024 * 1024,
// Set the maximum length of a transfer to 4 MiB
MaximumTransferSize = 4 * 1024 * 1024
}
};
// Upload data from a stream
await blobClient.UploadAsync(stream, options);
この例では、MaximumConcurrency
プロパティを使って、並列転送ワーカーの数を 2 に設定しています。 この構成では、最大 2 つの接続が同時に開かれ、アップロードを並列で実行できます。 最初の HTTP 範囲要求では、InitialTransferSize
プロパティで定義されている最大 8 MiB のデータのアップロードが試みられます。 シーク可能ストリームを使っているときは、InitialTransferSize
はアップロードのみに適用されることに注意してください。 BLOB のサイズが 8 MiB 未満の場合、操作を完了するために必要な要求は 1 つだけです。 BLOB のサイズが 8 MiB を超える場合は、後続のすべての転送要求の最大サイズは、MaximumTransferSize
プロパティで設定されている 4 MiB です。
アップロードのパフォーマンスに関する考慮事項
アップロードでは、ストレージ クライアント ライブラリは、StorageTransferOptions
インスタンスで定義されている値に基づいて、特定のアップロード ストリームを複数のサブアップロードに分割します。 REST 操作は、サブアップロードごとに専用の呼び出しで行われます。 BlobClient
オブジェクトまたは BlockBlobClient
オブジェクトの場合、この操作は Put Block です。 DataLakeFileClient
オブジェクトの場合は、この操作は Append Data です。 ストレージ クライアント ライブラリによって、これらの REST 操作が (転送オプションに応じて) 並列に管理されて、完全なアップロードが実行されます。
以下のセクションで説明するように、アップロード ストリームがシーク可能かシーク不可能かに応じて、クライアント ライブラリによるバッファーリングと InitialTransferSize
の処理方法が異なります。 シーク可能なストリームとは、ストリーム内の現在位置でのクエリと変更をサポートするストリームです。 .NET でのストリームについて詳しくは、Stream クラスのリファレンスをご覧ください。
Note
ブロック BLOB の最大ブロック数は 50,000 ブロックです。 したがって、ブロック BLOB の最大サイズは MaximumTransferSize
の 50,000 倍です。
アップロードの間のバッファーリング
Storage REST レイヤーでは、中断した REST アップロード操作の取得はサポートされていません。転送ごとに完了するか、失われます。 シーク不可能なストリーム アップロードの回復性を確保するため、ストレージ クライアント ライブラリは、アップロードを始める前に、個々の REST 呼び出しごとにデータをバッファーに格納します。 ネットワーク速度の制限だけでなく、このバッファーリング動作も、順番にアップロードする場合であっても、MaximumTransferSize
の値を小さくすることを検討すべき理由です。 MaximumTransferSize
の値を小さくすると、各要求および失敗した要求の各再試行でバッファーに格納されるデータの最大量が減ります。 あるサイズのデータ転送中にタイムアウトが頻繁に発生する場合は、MaximumTransferSize
の値を小さくすると、バッファーリング時間が短縮され、パフォーマンスが向上する可能性があります。
バッファーリングが発生するもう 1 つのシナリオは、ネットワーク スループットを最大にするため、並列 REST 呼び出しでデータをアップロードする場合です。 クライアント ライブラリには並列で読み取ることができるソースが必要であり、ストリームは順次であるため、ストレージ クライアント ライブラリは、アップロードを始める前に、個々の REST 呼び出しのデータをバッファーに格納します。 このバッファーリング動作は、指定したストリームがシーク可能な場合でも発生します。
非同期アップロード呼び出しの間のバッファーリングを回避するには、シーク可能なストリームを指定し、MaximumConcurrency
を 1 に設定する必要があります。 この方法はほとんどの状況で機能しますが、バッファーリングを必要とする他のクライアント ライブラリ機能がコードで使われている場合は、やはりバッファーリングが発生する可能性があります。
アップロードでの InitialTransferSize
シーク可能なストリームをアップロードに指定すると、ストリームの長さが InitialTransferSize
の値と照合されます。 ストリームの長さがこの値より小さい場合は、StorageTransferOptions
の他の値に関係なく、ストリーム全体が 1 つの REST 呼び出しとしてアップロードされます。 それ以外の場合は、前に説明したように、アップロードは複数の部分で行われます。 InitialTransferSize
は、シーク不可能なストリームには影響を与えず、無視されます。
ダウンロードのパフォーマンスに関する考慮事項
ダウンロードでは、ストレージ クライアント ライブラリは、StorageTransferOptions
インスタンスで定義されている値に基づいて、特定のダウンロード要求を複数のサブダウンロードに分割します。 REST 操作は、サブダウンロードごとに専用の呼び出しで行われます。 転送オプションに応じて、クライアント ライブラリにより、これらの REST 操作が並列に管理されて、完全なダウンロードが実行されます。
ダウンロードの間のバッファーリング
本文の内容で同時に複数の HTTP 応答を受信すると、メモリの使用量に影響します。 しかし、ストレージ クライアント ライブラリでは、ダウンロードされるコンテンツのバッファー ステップは明示的に追加されません。 着信した応答は順番に処理されます。 クライアント ライブラリは、HTTP 応答ストリームから、呼び出し元が提供する宛先ストリームまたはファイル パスへのストリームのコピー用に、16 KB のバッファーを構成します。
ダウンロードでの InitialTransferSize
ダウンロードの間に、ストレージ クライアント ライブラリは、他の操作を行う前に、InitialTransferSize
を使ってダウンロード範囲要求を 1 回行います。 この最初のダウンロード要求中に、クライアント ライブラリはリソースの合計サイズを把握します。 最初の要求ですべてのコンテンツが正常にダウンロードされた場合、操作は完了します。 そうでない場合、クライアント ライブラリは、完全なダウンロードが完了するまで、最大 MaximumTransferSize
の範囲要求を実行し続けます。
次のステップ
- この記事は、.NET の Blob Storage 開発者ガイドの一部です。 開発者ガイドの記事の完全な一覧については、「アプリケーションをビルドする」を参照してください。
- Azure Storage の操作のパフォーマンスに影響を与える可能性のある要因について詳しくは、「Blob Storage での待ち時間」をご覧ください。
- Blob Storage を使用するアプリのパフォーマンスを最適にするための設計に関する考慮事項の一覧については、「BLOB ストレージのパフォーマンスとスケーラビリティのチェックリスト」をご覧ください。