期間deltaT中に許可されるイベント数 nを制限する必要があります。私が考えることができる任意のアプローチ、スペースはO(m)です。ここで、mはdeltaTごとに送信されるイベント要求の最大数、またはO(deltaT/r)です。ここで、rは許容される解像度です。
編集: deltaT は、タイムスタンプに相対的なスライド時間ウィンドウです。
例: イベントのタイムスタンプの循環バッファーを保持します。イベント時にt-deltaTより前のすべてのタイムスタンプを切り取ります。タイムスタンプの数がnを超える場合、イベントを拒否します。タイムスタンプをバッファに追加します。
または、解像度rの現在に対する時間でインデックス付けされたサイズdeltaT/rの整数の循環バケット バッファを初期化します。ポインタiを維持します。イベントが発生すると、最後のイベントからの時間iをrで割った値だけ増やします。元のiと新しいiの間のバッファーをゼロにします。iでインクリメントします。盗聴者の合計がnを超える場合は拒否します。
より良い方法は何ですか?
上記の 2 番目の提案を 1 秒の固定デルタ Tと 10 ミリ秒の固定解像度でc# に実装しました。
public class EventCap
{
private const int RES = 10; //resolution in ms
private int _max;
private readonly int[] _tsBuffer;
private int p = 0;
private DateTime? _lastEventTime;
private int _length = 1000 / RES;
public EventCap(int max)
{
_max = max;
_tsBuffer = new int[_length];
}
public EventCap()
{
}
public bool Request(DateTime timeStamp)
{
if (_max <= 0)
return true;
if (!_lastEventTime.HasValue)
{
_lastEventTime = timeStamp;
_tsBuffer[0] = 1;
return true;
}
//A
//Mutually redundant with B
if (timeStamp - _lastEventTime >= TimeSpan.FromSeconds(1))
{
_lastEventTime = timeStamp;
Array.Clear(_tsBuffer, 0, _length);
_tsBuffer[0] = 1;
p = 0;
return true;
}
var newP = (timeStamp - _lastEventTime.Value).Milliseconds / RES + p;
if (newP < _length)
Array.Clear(_tsBuffer, p + 1, newP - p);
else if (newP > p + _length)
{
//B
//Mutually redundant with A
Array.Clear(_tsBuffer, 0, _length);
}
else
{
Array.Clear(_tsBuffer, p + 1, _length - p - 1);
Array.Clear(_tsBuffer, 0, newP % _length);
}
p = newP % _length;
_tsBuffer[p]++;
_lastEventTime = timeStamp;
var sum = _tsBuffer.Sum();
return sum <= 10;
}
}