ライブデータキャプチャのパーセンタイルを決定するアルゴリズムを探しています。
たとえば、サーバーアプリケーションの開発について考えてみます。
サーバーの応答時間は、17ミリ秒33ミリ秒52ミリ秒60ミリ秒55ミリ秒などです。
90パーセンタイル応答時間、80パーセンタイル応答時間などを報告すると便利です。
素朴なアルゴリズムは、各応答時間をリストに挿入することです。統計が要求されたら、リストをソートし、適切な位置で値を取得します。
メモリ使用量は、リクエストの数に比例して変化します。
限られたメモリ使用量で「おおよその」パーセンタイル統計を生成するアルゴリズムはありますか?たとえば、数百万のリクエストを処理する方法でこの問題を解決したいが、パーセンタイルの追跡には1キロバイトのメモリのみを使用したいとします(パーセンタイルはすべてのリクエストに対応します)。
また、分布に関する先験的な知識がないことも要求します。たとえば、バケットの範囲を事前に指定したくありません。
この問題には多くの優れた近似アルゴリズムがあると思います。優れたファーストカットアプローチは、固定サイズの配列(たとえば、1K相当のデータ)を使用することです。いくつかの確率pを修正します。リクエストごとに、確率pで、その応答時間を配列に書き込みます(配列内の最も古い時間を置き換えます)。配列はライブストリームのサブサンプリングであり、サブサンプリングは分布を保持するため、その配列で統計を実行すると、完全なライブストリームの統計の概算が得られます。
このアプローチにはいくつかの利点があります。事前情報を必要とせず、コーディングが簡単です。あなたはそれを素早くそして実験的に決定することができます、あなたの特定のサーバーのために、どの時点でバッファを増やすことは答えにごくわずかな影響しか与えません。それは、近似が十分に正確であるポイントです。
十分に正確な統計を提供するにはメモリが多すぎることがわかった場合は、さらに掘り下げる必要があります。適切なキーワードは、「ストリームコンピューティング」、「ストリーム統計」、そしてもちろん「パーセンタイル」です。 「怒りと呪い」のアプローチを試すこともできます。
より多くのデータを取得するときにメモリ使用量を一定に保ちたい場合は、どういうわけかそのデータを リサンプル する必要があります。これは、ある種の rebinning スキームを適用する必要があることを意味します。再ビニングを開始する前に、一定量の生の入力を取得するまで待つことができますが、それを完全に回避することはできません。
それで、あなたの質問は本当に「私のデータを動的にビニングする最良の方法は何ですか」と尋ねていますか?アプローチはたくさんありますが、受け取る値の範囲や分布についての仮定を最小限に抑えたい場合は、固定サイズkのバケット全体を平均するのが簡単なアプローチです。 、対数的に分布した幅。たとえば、一度に1000個の値をメモリに保持したいとします。 kのサイズ、たとえば100を選択します。最小解像度、たとえば1msを選択します。次に
このタイプの log-scaled アプローチは、一部のファイルシステムおよびメモリ割り当てアルゴリズムで使用される ハッシュテーブルアルゴリズム で使用されるチャンクシステムに似ています。データのダイナミックレンジが大きい場合にうまく機能します。
新しい値が入ってくると、要件に応じて、リサンプリングの方法を選択できます。たとえば、 移動平均 を追跡したり、 先入れ先出し を使用したり、その他のより高度な方法を使用したりできます。 1つのアプローチについては Kademlia アルゴリズムを参照してください( Bittorrent で使用)。
最終的に、リビニングはいくつかの情報を失う必要があります。ビニングに関する選択によって、失われる情報の詳細が決まります。別の言い方をすれば、一定サイズのメモリストアは、 ダイナミックレンジ と サンプリングの忠実度 の間のトレードオフを意味します。そのトレードオフをどのように行うかはあなた次第ですが、他のサンプリングの問題と同様に、この基本的な事実を回避することはできません。
あなたが本当に賛否両論に興味があるなら、このフォーラムの答えは十分であると期待することはできません。 サンプリング理論 を調べる必要があります。このトピックに関する膨大な量の研究が利用可能です。
価値があると思いますが、サーバー時間のダイナミックレンジは比較的小さいので、スケーリングを緩和して一般的な値のサンプリングを増やすと、より正確な結果が得られる可能性があります。
編集:コメントに答えるために、簡単なビニングアルゴリズムの例を次に示します。
新しい値が入ったとき:
90パーセンタイルを見つけるには、ビン10を並べ替えます。90パーセンタイルは、並べ替えられたリストの最初の値です(要素900/1000)。
古い値を破棄したくない場合は、代わりに使用する代替スキームを実装できます。たとえば、ビンがいっぱいになったとき(私の例では100個の値に達したとき)、最も古い50個の要素(つまり、リストの最初の50個)の平均を取り、それらの要素を破棄してから、新しい平均要素をに追加できます。ビン。51個の要素のビンが残り、49個の新しい値を保持するスペースがあります。これは、リビニングの簡単な例です。
再ビニングの別の例は ダウンサンプリング ;です。たとえば、ソートされたリストの5番目ごとの値を破棄します。
この具体的な例がお役に立てば幸いです。取り上げるべき重要な点は、一定のメモリエージングアルゴリズムを実現する方法がたくさんあるということです。要件を考慮して、何が満足できるかを判断できるのはあなただけです。
このトピックに関するブログ投稿 を公開しました。基本的な考え方は、「応答の95%パーセントが500ms〜600ms以下かかる」(500ms〜600msのすべての正確なパーセンタイルに対して)を優先して、正確な計算の要件を減らすことです。
任意のサイズのバケットをいくつでも使用できます(例:0ms-50ms、50ms-100ms、...ユースケースに合うものなら何でも)。通常、問題になることはありませんが、最後のバケット(つまり、> 5000ms)で特定の応答時間(たとえば、Webアプリケーションの場合は5秒)を超えるすべてのリクエスト。
新しくキャプチャされた応答時間ごとに、該当するバケットのカウンタをインクリメントするだけです。 n番目のパーセンタイルを見積もるには、合計が合計のnパーセントを超えるまでカウンターを合計するだけです。
このアプローチでは、バケットごとに8バイトしか必要としないため、1Kのメモリで128個のバケットを追跡できます。 50msの粒度を使用してWebアプリケーションの応答時間を分析するには十分すぎるほどです)。
例として、これが Google Chart 1時間のキャプチャデータから作成しました(バケットあたり200msの60個のカウンターを使用):
いいですね。 :) 私のブログでもっと読む 。
(この質問が出されてからかなり時間が経ちましたが、いくつかの関連する研究論文を指摘したいと思います)
過去数年間、データストリームのおおよそのパーセンタイルについてかなりの量の研究が行われてきました。完全なアルゴリズム定義を備えたいくつかの興味深い論文:
これらの論文はすべて、データストリーム全体の近似パーセンタイルを計算するための劣線形空間の複雑さを備えたアルゴリズムを提案しています。
論文「複数のパーセンタイルの同時推定のための順次手順」(Raatikainen)で定義されている単純なアルゴリズムを試してください。高速で、2 * m + 3マーカー(mパーセンタイルの場合)が必要で、正確な近似がすばやく行われる傾向があります。
大きな整数の動的配列T []か、T [n]が応答時間がnミリ秒であった回数をカウントするものを使用します。サーバーアプリケーションで実際に統計を実行している場合は、とにかく250ミリ秒の応答時間が絶対的な制限になる可能性があります。したがって、1 KBは、0〜250のミリ秒ごとに1つの32ビット整数を保持し、オーバーフロービン用にいくらかの余裕があります。より多くのビンを持つものが必要な場合は、1000ビンに対して8ビット数を使用し、カウンターがオーバーフローした瞬間(つまり、その応答時間で256番目の要求)に、すべてのビンのビットを1つ下げます(実質的に値を半分にします)すべてのビン)。これは、最も訪問されたビンがキャッチする遅延の1/127未満をキャプチャするすべてのビンを無視することを意味します。
本当に必要な場合は、リクエストの初日を使用して、適切な固定のビンのセットを作成することをお勧めします。パフォーマンスに敏感なライブアプリケーションでは、動的なものはすべて非常に危険です。そのパスを選択した場合は、自分が何をしているのかをよく理解するか、いつかベッドから呼び出されて、統計トラッカーが本番サーバーで突然90%のCPUと75%のメモリを消費している理由を説明します。
追加の統計について:平均と分散については、メモリをほとんど消費しない 素敵な再帰アルゴリズム がいくつかあります。 中心極限定理 は、十分に多数の独立変数から生じる分布が正規分布(完全に定義されている)に近づくと述べているため、これら2つの統計はそれ自体で多くの分布に十分に役立ちます。平均と分散)最後のN(Nは十分に大きいが、メモリ要件によって制約されている)で 正規性検定 のいずれかを使用して、正規性の仮定がまだ成立するかどうかを監視できます。