3

成功イベントと失敗イベントをディスパッチするクラスがあり、そのクラスの最後の X 秒間の平均失敗数/合計イベント数の統計を維持する必要があります。

循環リンク リストを使用し、各イベントに成功または失敗のノードを追加する方法に沿って何かを考えていました。次に、失敗したノードの数とリスト内の合計ノードの数を数えますが、これには 2 つの大きな欠点があります。

  1. 「最後の X 秒」の要件を考慮して、リストのサイズを常に拡大/縮小する必要があります (1 秒あたりのイベント数は変更される可能性があります)。
  2. リストを常にループし、すべてのイベントをカウントする必要があります (1 秒間に数百のイベントが発生する可能性があるため、コストがかかる可能性があります)。

最後の X 秒間に受信したサンプルのリストから平均値を計算する別の方法を知っている人はいますか?

4

6 に答える 6

1

通常、これらの種類のサンプラーには、通常指定する追加のものが 1 つあります。それはサンプラーの解像度です。

あなたの説明を仮定すると、サンプラーの解像度は1秒または1ティックのいずれかになります。

サンプラーに必要な解像度が 1 秒である場合、十分に機能する可能性のあるアルゴリズムの命題を次に示します。

  • リンクリストを作成します。リスト ノードは [タイムスタンプ、成功回数、失敗回数、previousNode] を保持します。
  • lastNodeリストの最後のノードへの参照と最初のノードへの参照を保存しますfirstNode(lastNodeはリストの末尾になりfirstNode、最後に追加されたノードは先頭になります)。
  • 2 つのグローバル変数 gSuccess、gFail、最後の X 秒の時間枠での成功と失敗の合計を保持します。

新しいイベントを受信すると:

  • イベント [タイムスタンプ] を firstNode と比較するtimestamp

    IF (eventTimestamp.TotalSeconds > firstNode.TotalSeconds)

    • リストの先頭 (firsNode の前に挿入) に新しいノード a を追加し、成功と失敗のカウントを 0 にします。
    • firstNode.Previous = newNode
    • firsNode = newNode;

    END IF

    • firstNode.Success または firstNode.Failure のカウントを 1 増やします
    • * gSuccess または gFail を 1 ずつ増やします

    (各イベントが追加された後) REMOVE_EXPIRED_NODES

  • WHILE ( lastNode != nil AND currentTime.TotalSeconds - lastNode.TotalSeconds > X)

    • gSuccess -= lastNode.Succes (削除するノードごとに gSuccess を減らす 成功回数)
    • gFail -= lastNode.Fail (削除するノードの Fail 数によって gFail を減らします)
    • lastNode を削除

    終了まで

gFail と gSuccess を取得する前に、常に REMOVE_EXPIRED_NODES を付ける必要があります。

このアプローチの利点:

  • Fail および Success のグローバル カウンタは、すべてのイベントから再計算されるわけではありませんが、代わりに徐々に増加するイベントが追加され、X 秒より古いノードがリストから削除されると減少します。

  • すべてのイベントのリストを保存する代わりに、1 秒のサンプラー解像度を使用します (1 秒あたり数百の場合があり、1 秒あたり合計 2 つのリスト操作が実行されるようにします (追加 + 削除操作))。

  • イベントの数に関係なく、1 秒あたりのリスト操作数の平均は 2 (追加操作 1 回、削除操作 1 回) です。

于 2009-02-17T11:29:03.810 に答える
1

あなたの要件はどの程度具体的ですか?枠にとらわれずに考えることができる場合、単純なガイガー カウンター アルゴリズム、別名無限インパルス応答 (IIR) デジタル フィルターは移動「平均」を計算します (「平均」の定義方法によって異なります)。メモリ フットプリントを削減し、数行のコードしか必要としません。

于 2009-02-17T17:37:49.163 に答える