2017-06-23 1 views
-1

私のアプリケーションでは、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++; 
      } 
     } 
    } 
} 
+0

コードが50個のストリームに参加していますか? where節はありませんか? WHERE句なしでSQLデータベースに50個のテーブルを結合すると何が得られるのか知っています--->おそらく非常に多くの行があります。私はあなたが望むものは50の独立した声明だと思います。または、ここに記載されている2つのステートメント、http://espertech.com/esper/solution_patterns.php#expiry-3 – user650839

+0

@ user650839:実際には、[Nesper documentation]に基づいたストリームレベルフィルタを使用してフィルタリングを行っています(http: //www.espertech.com/esper/release-5.5.0/esper-reference/html_single/index.html#perf-tips-5)は、WHERE原因と比較して高度に最適化されています。 – Isaac

+0

@ user650839:あなたが提供したリンクは興味深いようです。問題は私のアプリケーションのステートメントがより複雑で、私はここで非常に単純化された例を提供しています。私はフィルタリングのために '分割された文脈 'を採用しながら、それらの文を基本的なEPL文に写像する方法があるかどうかを理解しなければなりません。 – Isaac

答えて

関連する問題