Python を使用したアップロードとダウンロードのパフォーマンス チューニング

アプリケーションが Python 用 Azure Storage クライアント ライブラリを使ってデータを転送する場合、要求の速度、メモリ使用量、さらには成功または失敗に影響を与える可能性のあるいくつかの要因があります。 データ転送のパフォーマンスと信頼性を最大にするには、アプリが実行される環境に基づいて、クライアント ライブラリ転送オプションを事前に構成することが重要です。

この記事では、データ転送オプションのチューニングに関するいくつかの考慮事項について説明します。 クライアント ライブラリを適切にチューニングすると、複数の要求にデータを効率的に分散できるため、操作速度、メモリ使用量、ネットワークの安定性が向上する可能性があります。

アップロードのパフォーマンス チューニング

データ転送オプションを適切に調整することは、アップロードのパフォーマンスの信頼性の鍵となります。 ストレージ転送は、これらの引数の値に基づいて、複数のサブ転送に分割されます。 サポートされる最大転送サイズは、操作とサービスのバージョンによって異なるため、ドキュメントを調べて制限を確認してください。 Blob Storage での転送サイズの制限について詳しくは、「BLOB ストレージのスケール ターゲット」をご覧ください。

アップロードの転送オプションを設定する

次の引数は、アプリのニーズに基づいて調整できます。

  • max_single_put_size: 1 つの要求でアップロードされる BLOB の最大サイズ。 既定値は 64 MiB です。
  • max_block_size: ブロック BLOB をチャンク単位でアップロードするときの転送の最大長 (バイト単位)。 既定値は 4 MiB です。
  • max_concurrency: 並列で使用できるサブ転送の最大数。

注意

指定されていない場合、各データ転送オプションの既定値がクライアント ライブラリで使用されます。 通常、これらの既定値は、データ センター環境でのパフォーマンスは優れていますが、ホーム コンシューマー環境には適していない可能性があります。 データ転送オプションの調整が不十分な場合、処理時間が非常に長くなる可能性があり、要求がタイムアウトすることさえあります。 これらの値を事前にテストし、アプリケーションと環境のニーズに基づいて調整することをお勧めします。

max_single_put_size

max_single_put_size 引数は、1 回の要求のアップロードの最大 BLOB サイズ (バイト単位) です。 BLOB サイズが max_single_put_size 以下 の場合、BLOB は 1 つの Put Blob 要求でアップロードされます。 BLOB サイズが max_single_put_size より大きい場合、または BLOB サイズが不明な場合、BLOB は一連の Put Block 呼び出しの後に Put Block List を使用してチャンク単位でアップロードされます。

max_block_size で指定する値により、max_single_put_size に対して定義する値は "制限されない" ことに注意してください。 max_single_put_size 引数では、操作全体をサブ転送なしで一度に実行するための、1 つの要求の個別のサイズ制限を定義します。 多くの場合、max_single_put_size は、max_block_size に対して定義した値より大きくはないにしても、"少なくとも" それと同じ大きさにする必要があります。 データ転送のサイズによっては、このようにすると、転送が 1 つの要求で完了し、複数の要求のオーバーヘッドが回避されるため、パフォーマンスが向上する可能性があります。

状況に最適な値がわからない場合は、max_block_size に使われているのと同じ値に max_single_put_size を設定するのが安全なオプションです。

max_block_size

max_block_size 引数は、ブロック BLOB をチャンク単位でアップロードするときの転送の最大長 (バイト単位) です。 前に説明したように、この値によって max_single_put_size が制限されることは "なく"、max_block_size より大きくできます。

データ移動の効率性を維持するため、クライアント ライブラリではすべての転送で max_block_size 値に常に達するとは限りません。 転送サイズでサポートされる最大値は、操作によって異なる場合があります。 Blob Storage での転送サイズの制限について詳しくは、「BLOB ストレージのスケール ターゲット」の表をご覧ください。

コードの例

次のコード例は、BlobClient オブジェクトの作成時にデータ転送オプションを指定する方法と、そのクライアント オブジェクトを使用してデータをアップロードする方法を示しています。 このサンプルで提供される値は、推奨を意図したものではありません。 これらの値を適切にチューニングするには、アプリの特定のニーズを考慮する必要があります。

def upload_blob_transfer_options(self, account_url: str, container_name: str, blob_name: str):
    # Create a BlobClient object with data transfer options for upload
    blob_client = BlobClient(
        account_url=account_url, 
        container_name=container_name, 
        blob_name=blob_name,
        credential=DefaultAzureCredential(),
        max_block_size=1024*1024*4, # 4 MiB
        max_single_put_size=1024*1024*8 # 8 MiB
    )
    
    with open(file=os.path.join(r'file_path', blob_name), mode="rb") as data:
        blob_client = blob_client.upload_blob(data=data, overwrite=True, max_concurrency=2)

この例では、メソッド呼び出しの max_concurrency 引数を使って、並列転送ワーカーの数を 2 に設定しています。 この構成では、最大 2 つの接続が同時に開かれ、アップロードを並列で実行できます。 クライアントのインスタンス化時に、max_single_put_size 引数を 8 MiB に設定します。 BLOB のサイズが 8 MiB 未満の場合、アップロード操作を完了するために必要な要求は 1 つだけです。 BLOB サイズが 8 MiB を超える場合、max_block_size 引数によって設定された最大チャンク サイズ 4 MiB のチャンク単位で BLOB が アップロードされます。

アップロードのパフォーマンスに関する考慮事項

アップロード時に、Storage クライアント ライブラリは、クライアントの構築時に定義された構成オプションに基づいて、特定のアップロード ストリームを複数のサブアップロードに分割します。 REST 操作は、サブアップロードごとに専用の呼び出しで行われます。 BlobClient オブジェクトの場合、この操作は Put Block です。 ストレージ クライアント ライブラリによって、これらの REST 操作が (転送オプションに応じて) 並列に管理されて、完全なアップロードが実行されます。

クライアント ライブラリがバッファリングをどのように処理するかについては、次のセクションで説明します。

Note

ブロック BLOB の最大ブロック数は 50,000 ブロックです。 したがって、ブロック BLOB の最大サイズは max_block_size の 50,000 倍です。

アップロードの間のバッファーリング

Storage REST レイヤーでは、中断した REST アップロード操作の取得はサポートされていません。転送ごとに完了するか、失われます。 ストリーム アップロードの回復性を確保するため、ストレージ クライアント ライブラリは、アップロードを始める前に、個々の REST 呼び出しごとにデータをバッファーに格納します。 ネットワーク速度の制限だけでなく、このバッファーリング動作も、順番にアップロードする場合であっても、max_block_size の値を小さくすることを検討すべき理由です。 max_block_size の値を小さくすると、各要求および失敗した要求の各再試行でバッファーに格納されるデータの最大量が減ります。 あるサイズのデータ転送中にタイムアウトが頻繁に発生する場合は、max_block_size の値を小さくすると、バッファーリング時間が短縮され、パフォーマンスが向上する可能性があります。

既定では、SDK は同時サブアップロード要求ごとに max_block_size バイトのデータをバッファーに格納しますが、次の条件が満たされた場合、メモリ使用量は要求あたり 4 MiB に制限できます。

  • max_block_size 引数は min_large_block_upload_threshold より大きくなければなりません。 min_large_block_upload_threshold 引数は、クライアントのインスタンス化中に定義でき、メモリ効率の高いアルゴリズムを使用するために必要な最小チャンク サイズ (バイト単位) です。 min_large_block_upload_threshold 引数の既定値は 4*1024*1024 + 1 です。
  • 指定されたストリームはシーク可能である必要があります。 シーク可能なストリームとは、ストリーム内の現在位置でのクエリと変更をサポートするストリームです。
  • BLOB はブロック BLOB である必要があります。

この方法はほとんどの状況に適用されますが、バッファリングを必要とする他のクライアント ライブラリ機能がコードで使われている場合は、バッファリングがさらに発生する可能性があります。

ダウンロードのパフォーマンス チューニング

データ転送オプションを適切に調整することは、ダウンロードのパフォーマンスの信頼性の鍵となります。 ストレージ転送は、これらの引数の値に基づいて、複数のサブ転送に分割されます。

ダウンロードの転送オプションを設定する

次の引数は、アプリのニーズに基づいて調整できます。

  • max_chunk_get_size: BLOB のダウンロードに使用される最大チャンク サイズ。 既定値は 4 MiB です。
  • max_concurrency: 並列で使用できるサブ転送の最大数。
  • max_single_get_size: 1 回の呼び出しでダウンロードされる BLOB の最大サイズ。 BLOB の合計サイズが max_single_get_size を超える場合、BLOB データの残りの部分はチャンクでダウンロードされます。 既定値は 32 MiB です。

コードの例

def download_blob_transfer_options(self, account_url: str, container_name: str, blob_name: str):
    # Create a BlobClient object with data transfer options for download
    blob_client = BlobClient(
        account_url=account_url, 
        container_name=container_name, 
        blob_name=blob_name,
        credential=DefaultAzureCredential(),
        max_single_get_size=1024*1024*32, # 32 MiB
        max_chunk_get_size=1024*1024*4 # 4 MiB
    )

    with open(file=os.path.join(r'file_path', 'file_name'), mode="wb") as sample_blob:
        download_stream = blob_client.download_blob(max_concurrency=2)
        sample_blob.write(download_stream.readall())

ダウンロードのパフォーマンスに関する考慮事項

ダウンロード時に、Storage クライアント ライブラリは、クライアントの構築時に定義された構成オプションに基づいて、特定のダウンロード要求を複数のサブダウンロードに分割します。 REST 操作は、サブダウンロードごとに専用の呼び出しで行われます。 転送オプションに応じて、クライアント ライブラリにより、これらの REST 操作が並列に管理されて、完全なダウンロードが実行されます。

ダウンロードの max_single_get_size

ダウンロードの間に、ストレージ クライアント ライブラリは、他の操作を行う前に、max_single_get_size を使ってダウンロード範囲要求を 1 回行います。 この最初のダウンロード要求中に、クライアント ライブラリはリソースの合計サイズを把握します。 最初の要求ですべてのコンテンツが正常にダウンロードされた場合、操作は完了します。 そうでない場合、クライアント ライブラリは、完全なダウンロードが完了するまで、最大 max_chunk_get_size の範囲要求を実行し続けます。

次のステップ