私のアプリケーションでは、CEPエンジンとしてNesperを使用してイベントを処理しています。win of windowを使用した場合のCPU /メモリの使用量が高い:時間
私は、次のEPL文をモデル化しようとしています:
- イベントの
Value
フィールドは限られた窓の時間平均されています。 - これらの平均値のいずれかが
1
の値に一致すると、イベントが生成されます。
私はこれをモデル化しました:
SELECT (
(AVG(ParameterEvent1.Value) = 1) OR
(AVG(ParameterEvent2.Value) = 1)
...
(AVG(ParameterEvent50.Value) = 1)
) AS BooleanValue
FROM
ParameterEvent(Id = 1).win:time(3 sec) AS ParameterEvent1,
ParameterEvent(Id = 2).win:time(3 sec) AS ParameterEvent2
...
ParameterEvent(Id = 50).win:time(3 sec) AS ParameterEvent50
そして、別のスレッドで、私は50イベント/秒の安定した速度でエンジンにパラメータ値を供給しています。
この設定は、com.espertech.esper.client.EPException: ReaderWriterLock timeout expired
例外が発生するまで、巨大なCPUとRAMの使用を引き起こします。
私はこの問題を引き起こしているのだろうか。 ウィンドウをwin:time(3 sec)
からstd:lastevent()
に変更すると、この問題は解決します。しかし、イベントを生成する前に、パラメータの値が1
から3秒であることを確認するためのウィンドウが必要です。
完全なデモコードは次のとおりです。あなたはそれを実行するためにNesper
パッケージをインストールする必要があります。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using com.espertech.esper.client;
namespace NesperTester
{
class Program
{
public class ParameterEvent
{
public int Id { get; set; }
public int Value { get; set; }
}
static EPServiceProvider engine;
const int NParameters = 50;
static void Main(string[] args)
{
engine = EPServiceProviderManager.GetDefaultProvider();
engine.EPAdministrator.Configuration.AddEventType("ParameterEvent", typeof(ParameterEvent));
CreateEPLStatement();
Task.Factory.StartNew(() => SimulateParameterChange(), TaskCreationOptions.LongRunning);
System.Threading.Thread.Sleep(int.MaxValue);
}
static void CreateEPLStatement()
{
const int windowLength = 3;
var sb = new StringBuilder();
for (int i = 1; i <= NParameters; i++)
{
sb.AppendFormat("(AVG(ParameterEvent{0}.Value) = 1) OR ", i);
}
var rule = sb.ToString();
rule = rule.Remove(rule.Length - 4, 4);
sb.Clear();
for (int paramId = 1; paramId <= NParameters; paramId++)
{
sb.AppendFormat("ParameterEvent(Id = {0}).win:time({1} sec) AS ParameterEvent{0}, ", paramId, windowLength);
//sb.AppendFormat("ParameterEvent(Id = {0}).std:lastevent() AS ParameterEvent{0}, ", paramId, windowLength);
}
var selectSources = sb.ToString();
selectSources = selectSources.Remove(selectSources.Length - 2, 2);
var eplStr = string.Format("SELECT ({0}) AS BooleanValue FROM {1}", rule, selectSources);
var statementName = string.Format("statement1");
var statement = engine.EPAdministrator.CreateEPL(eplStr, statementName, null);
statement.Start();
statement.Events += Statement_Events;
}
static bool PrevState = false;
static void Statement_Events(object sender, UpdateEventArgs e)
{
var underlying = e.NewEvents[0].Underlying as Dictionary<string, object>;
if (underlying.Last().Value == null)
{
Console.WriteLine("Statement value is unknown");
}
else
{
var statementValue = (bool)underlying.First().Value;
if (statementValue != PrevState)
{
PrevState = statementValue;
Console.WriteLine("Statement is {0}", statementValue);
}
}
}
static void SimulateParameterChange()
{
int counter = 0;
while (true)
{
for (int i = 1; i <= NParameters; i++)
{
var evt = new ParameterEvent();
evt.Id = i;
if (i == 1 && (counter/4) % 2 == 0)
{
evt.Value = 1;
}
else
{
evt.Value = 0;
}
engine.EPRuntime.SendEvent(evt);
System.Threading.Thread.Sleep(1000/NParameters);
}
counter++;
}
}
}
}
コードが50個のストリームに参加していますか? where節はありませんか? WHERE句なしでSQLデータベースに50個のテーブルを結合すると何が得られるのか知っています--->おそらく非常に多くの行があります。私はあなたが望むものは50の独立した声明だと思います。または、ここに記載されている2つのステートメント、http://espertech.com/esper/solution_patterns.php#expiry-3 – user650839
@ user650839:実際には、[Nesper documentation]に基づいたストリームレベルフィルタを使用してフィルタリングを行っています(http: //www.espertech.com/esper/release-5.5.0/esper-reference/html_single/index.html#perf-tips-5)は、WHERE原因と比較して高度に最適化されています。 – Isaac
@ user650839:あなたが提供したリンクは興味深いようです。問題は私のアプリケーションのステートメントがより複雑で、私はここで非常に単純化された例を提供しています。私はフィルタリングのために '分割された文脈 'を採用しながら、それらの文を基本的なEPL文に写像する方法があるかどうかを理解しなければなりません。 – Isaac