📊

[翻訳] Concurrent Segment Search のフォローアップ: パフォーマンス分析

に公開

https://opensearch.org/blog/concurrent-search-follow-up/

2023 年 10 月に、実験的機能として OpenSearch に Concurrent Segment Search を導入 しました。セグメントを並行して検索することで、さまざまなワークロードで検索レイテンシーが改善されます。この機能は OpenSearch 2.12 で一般提供 (GA) となりました。ぜひお試しください。ここでは、さまざまな実世界のシナリオをシミュレーションしたパフォーマンス結果を共有します。特に、利用可能なシステムリソースが減少し、同時実行数が増加した場合のパフォーマンス傾向を見ていきます。

Concurrent Segment Search は、ノード上の各シャードレベルの検索リクエストを スライス と呼ばれる複数の実行タスクに分割します。スライスは、search スレッドプールとは別の index_searcher スレッドプール内の別々のスレッドで並行して実行できます。各スライスは、関連付けられたセグメント内を検索します。すべてのスライスの実行が完了すると、すべてのスライスから収集された結果が結合 (リデュース) され、コーディネーターノードに返されます。index_searcher スレッドプールは、各シャード検索リクエストのスライスを実行するために使用され、ノード上のすべてのシャード検索リクエスト間で共有されます。デフォルトでは、index_searcher スレッドプールには、利用可能なプロセッサ数の 2 倍のスレッドがあります。

パフォーマンス結果

パフォーマンステストには、32 vCPU と 64 の index_searcher スレッドプールサイズを持つ標準的な r5.8xlarge インスタンスタイプを使用しました。これにより、現実的なインスタンスでさまざまな同時実行数とクラスター負荷のシナリオを探索し、スライス数と検索クライアント数を増やした際のパフォーマンスをより正確に把握できました。

以前の記事 では、長時間実行される CPU 集約型の操作で最も強いパフォーマンス改善が示され、match_all のような高速なクエリでは改善がほとんどないか、Concurrent Segment Search のオーバーヘッドによるわずかなパフォーマンス低下が見られることを示しました。この記事では、さまざまなクラスター負荷条件下でパフォーマンスがどのように変化するかに焦点を当てたいため、OpenSearch Benchmark を使用した nyc_taxisbig5 ワークロードの長時間実行操作のより小さなサブセットを見ていきます。また、OpenSearch Benchmark が提供するワークロード全体の p90 システムメトリクスを報告します。これは長時間実行操作に最も関連性があります。

まず、単一シャードと単一検索クライアントを使用してパフォーマンスベースラインを確立しました。この構成は、Concurrent Segment Search を使用する際の理論上の最良のシナリオです。この構成では、一度に最大 1 つのシャードレベル検索リクエストが処理されるため、各リクエストは最大限のリソースを使用します。

以下のセクションでは、パフォーマンス結果を示します。Concurrent Segment Search を「CS」と略します。

クラスター構成 1

  • インスタンスタイプ: r5.8xlarge (32 vCPU、256 GB RAM)
  • ノード数: 1
  • シャード数: 1
  • 検索クライアント数: 1
  • Concurrent Search スレッドプールサイズ: 64

p90 クエリレイテンシーの比較

操作 CS 無効 (ms) CS 有効 (Lucene デフォルトスライス) (ms) 改善率 CS 有効 (固定スライス数=2) (ms) 改善率 CS 有効 (固定スライス数=4) (ms) 改善率
range-auto-date-histo-with-metrics (big5) 21757 4178 81% 11710 46% 6915 68%
range-auto-date-histo (big5) 7950 1486 81% 4341 45% 2555 67%
query-string-on-message (big5) 143 49 66% 81 43% 59 58%
keyword-in-range (big5) 127 58 54% 87 31% 70 44%
distance_amount_agg (nyc_taxis) 12403 2921 76% 6642 46% 3633 71%

システムメトリクス (big5)

メトリクス CS 無効 CS 有効 (Lucene デフォルトスライス) CS 有効 (固定スライス数=2) CS 有効 (固定スライス数=4)
p90 CPU 3% 36% 6% 12%
p90 JVM 54% 56% 54% 54%
最大 index_searcher アクティブスレッド 17 2 4

最初の記事で共有した初期パフォーマンス結果と同様に、より大きな r5.8xlarge インスタンスタイプでも、長時間実行される CPU 集約型の操作で強いパフォーマンス改善が見られます。システムリソース使用率については、アクティブな Concurrent Search スレッド数が増加すると、予想どおり CPU 使用率が増加します。ただし、p90 JVM ヒープ使用率は、同時実行数の増加とほとんど相関がないようです。

一歩引いて考えると、Concurrent Segment Search を使用することで得られる理論上の最大パフォーマンス向上は、同時実行数が 2 倍になるごとにシャードレベル検索リクエストレイテンシーが約 50% 改善することです。例えば、Concurrent Search なしから 2 スライスの Concurrent Search に移行すると、理論上の最大パフォーマンス改善は 50% です。4 スライスに増やすと最大パフォーマンス改善は 75%、8 スライスでは 87.5% になります。また、同時実行数が 2 倍になるごとに、スライス間で同じ作業分散を仮定すると、CPU 使用率もおおよそ 2 倍になると予想されます。これは、2 倍の CPU スレッドが使用されるためですが、より短い時間で済みます。

それを念頭に置くと、クラスター構成 1 でも、スライスレベルの同時実行数を増やすにつれて、パフォーマンス改善の収穫逓減が観察され始めます。この変化は、主に重複作業と、スライス数が増加するにつれてスライスレベルの検索結果をリデュースするために必要な追加の労力に起因します。

range-auto-date-histo-with-metrics のパフォーマンス改善と CPU 使用率

以下の表は、range-auto-date-histo-with-metrics 操作のパフォーマンス改善データの例を示しています。

比較 パフォーマンス改善率 追加 CPU 使用率 (p90)
CS 無効から 2 スライス 46% 3%
2 スライスから 4 スライス 22% 6%
4 スライスから Lucene デフォルトスライス数 13% 24%

CS 無効と 2 スライスの Concurrent Search を比較すると、わずか 3% の追加 CPU で 46% のパフォーマンス改善が得られることがわかります。ただし、より多くの CPU を使用するためにスライス数を増やすと、パフォーマンス改善は減少します。4 スライスから Lucene デフォルトスライス数に移行すると、24% の追加 CPU 使用率のコストで、わずか 13% のパフォーマンス改善しか得られないことがわかります。

もちろん、現実世界では、クラスターが一度に 1 つの検索リクエストのみを処理することはほとんどありません。クラスターの負荷が増加するにつれて Concurrent Segment Search のパフォーマンスがどのように変化するかを理解するために、いくつかの追加のクラスター構成でパフォーマンステストを実行しました。

クラスター構成 4

  • インスタンスタイプ: r5.8xlarge (32 vCPU、256 GB RAM)
  • ノード数: 1
  • シャード数: 1
  • 検索クライアント数: 8
  • Concurrent Search スレッドプールサイズ: 64

この構成では、検索クライアント数を 8 に倍増しました。システムリソース使用率メトリクスに基づくと、4 スライスと Lucene デフォルトスライスの両方のケースで 100% の CPU 使用率に達していることがわかります。予想どおり、このシナリオでスライス数を増やすと、収穫逓減がさらに顕著になり、場合によってはわずかなパフォーマンス低下さえ見られます。

range-auto-date-histo-with-metrics のパフォーマンス改善と CPU 使用率

比較 パフォーマンス改善率 追加 CPU 使用率 (p90)
CS 無効から 2 スライス 46% 24%
2 スライスから 4 スライス -1% 50%
4 スライスから Lucene デフォルトスライス数 0% 1%

クラスター構成 3 では、CPU 使用率が 100% に達したときに 4 スライスから Lucene デフォルトスライス数に移行してもほとんど利点がないことがわかりました。同様に、このシナリオで 2 スライスから 4 スライスに移行しても、CPU 使用率が 100% に達すると最小限の利点しか得られません。多数の検索クライアントが同時にリクエストを送信するシナリオでは、クラスター上のスライスレベルの同時実行数を増やしてもパフォーマンス向上が得られにくいことが明確にわかります。これは、CPU リソース使用率が 1 秒あたりの最大クエリ数に達し始めるためです。

構成の比較

range-auto-date-histo-with-metrics の構成比較

クラスター構成 CS 無効から 2 スライスへの改善率 追加 CPU 使用率 2 スライスから 4 スライスへの改善率 追加 CPU 使用率 4 スライスから Lucene デフォルトへの改善率 追加 CPU 使用率
1 シャード / 1 クライアント 46% 3% 22% 6% 12% 24%
1 シャード / 2 クライアント 45% 6% 22% 13% 10% 35%
1 シャード / 4 クライアント 45% 12% 22% 24% 2% 44%
1 シャード / 8 クライアント 46% 24% -1% 50% 0% 1%

ここでの主な結論は、利用可能な CPU リソースがある場合はいつでも、同時実行数をさらに増やすことでパフォーマンスを改善できるということです。ただし、CPU リソースが完全に使用されると、同時実行数を増やしてもパフォーマンス向上は見られなくなり、わずかな低下さえ見られる可能性があります。さらに、CPU リソースが利用可能な場合でも、単一リクエストの同時実行数を増やすことには収穫逓減があります。これは、並行部分でのスライス間の重複作業とリデュースフェーズでの順次作業の組み合わせによって追加のオーバーヘッドが発生するためです。これらの CPU リソースの可用性が低下すると、同時実行数の収穫逓減の効果がさらに増幅されます。

観察事項

Concurrent Segment Search に関連するパフォーマンスの増減は、通常、以下の 4 つの理由のいずれかに起因します。

  • 第一に、セグメントスライス数が多い場合、index_searcher スレッドプールがいっぱいになります。スライスのシャード検索タスクを実行するスレッドが利用できない場合、スライスは他のスライスの処理が完了するまでキューで待機します。
  • 第二に、アクティブスレッド数が CPU コア数より多い場合、CPU コアがタスクを多重化するため、個々のスレッドの処理時間が長くなる可能性があります。
  • 第三に、特定のクエリ実装は、スライス数が増加するにつれて一部のクエリがより多くの重複作業を実行する可能性があるため、同時実行数を増やす際のパフォーマンスに大きな影響を与える可能性があります。
  • 第四に、リデュースフェーズはすべてのセグメントスライスに対して順次実行されます。リデュースオーバーヘッドが大きい場合、ドキュメントを並行して検索することで得られる利点を相殺する可能性があります。

まとめ

要約すると、使用するセグメントスライス数を選択する際には、追加のスライスによって生成される追加の並列化が追加の処理オーバーヘッドを上回るかどうかを判断するために、独自のベンチマークを実行することが重要です。Concurrent Segment Search は本番環境で使用する準備ができており、この プロジェクトボード で進行中の改善を追跡できます。

また、時間の経過に伴うパフォーマンスの可視性を提供するために、この記事で言及したすべてのテストワークロードをカバーする Concurrent Segment Search の夜間パフォーマンス実行を OpenSearch Performance Benchmarks で公開します。

Concurrent Segment Search を始めるためのガイドラインについては、General guidelines を参照してください。

OpenSearch Project

Discussion