【问题标题】:Best practise for parsing trace data [closed]解析跟踪数据的最佳实践 [关闭]
【发布时间】:2016-01-21 14:11:09
【问题描述】:

我的应用正在解析不断传入的跟踪。
我在外部库中预编译了正则表达式。 读取和分析传入数据是在以下函数中完成的,该函数在工作线程中运行。

出于演示目的,我已经剥离了代码。目前它使用了 30 种不同的正则表达式,这些正则表达式是按顺序检查的。

    private void Filter()
    {
        Regex rgx_1 = new RegEx_1();
        Regex rgx_2 = new RegEx_2();
        ...
        Regex rgx_N = new RegEx_N();

        uint index = 0;
        while (!FilterThread.CancellationPending)
        {
            BufferLength = (int)Source.GetItemCount() - 1;
            if (index <= BufferLength)
            {
                item = (ColorItem)Source.GetItem(index);
                if (item != null)
                {
                    tracecontend = item.GetItemSummary();
                    if (rgx_1.IsMatch(tracecontend))
                    {
                        current_trace = new TraceLine(index, tracecontend, GROUP_1);
                    }
                    else if (rgx_2.IsMatch(tracecontend))
                    {
                        current_trace = new TraceLine(index, tracecontend, GROUP_2);
                    }
                    else if (rgx_3.IsMatch(tracecontend))
                    {
                        current_trace = new TraceLine(index, tracecontend, GROUP_3);
                    }
                    ...
                    else if (rgx_N.IsMatch(tracecontend))
                    {
                        current_trace = new TraceLine(index, tracecontend, GROUP_N);
                    }
                    listBox.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new AddTraceDelegate(AddTrace), current_trace);
                }
                index++;
                System.Threading.Thread.Sleep(1);
            }
        }
    }

通过这种方法,我每秒可以处理多达 500 条跟踪,这对于实时跟踪来说已经足够了。但是读取包含多达 2.000.000 条轨迹的文件仍然需要相当长的时间。

您知道如何加快执行速度并提高吞吐量吗?

是否有人对这种情况有最佳实践?

编辑: 这是一个正则表达式的示例

           compilationList.Add(new RegexCompilationInfo(@"SomeTextToFilterFor(.*?)",
                   RegexOptions.IgnoreCase | RegexOptions.CultureInvariant,
                   "RegEx_1",
                   "Utilities.RegularExpressions",
                   true));
          RegexCompilationInfo[] compilationArray = new RegexCompilationInfo[compilationList.Count];
          AssemblyName assemName = new AssemblyName("RegexLib, Version=1.0.0.1001, Culture=neutral, PublicKeyToken=null");
          compilationList.CopyTo(compilationArray);
          Regex.CompileToAssembly(compilationArray, assemName);

【问题讨论】:

  • 这看起来像是 Optimize performance with multiple calls to Regex.IsMatch on large text 的副本。关键是:1)你在使用有效的正则表达式吗? 2)您是否使用RegexOptions.Compiled 将它们声明为私有静态只读字段? (通过查看问题我猜不是)。
  • tracecontend 的平均长度是多少?
  • 我相信你有 .*.*? 的正则表达式模式。检查它们的效率。如果您使用正则表达式解析 HTML,请重新考虑该方法。
  • @WiktorStribiżew 我已经编辑了问题并添加了一个正则表达式。我尽可能少地使用 .* 或 .*?只有在其中一些我有 (.*?) 或 (/d+) 以获得一些值以进行进一步处理
  • @Thomas 一行大约是。 100 字节长

标签: c# regex multithreading performance


【解决方案1】:

有很多方法可以提高速度。

如果可能的话,结合你的正则表达式

Regex 是一种状态机,可以回溯,但会尝试一次性完成所有工作。一口气胜过多次比赛。

例如:

aaaaaab | aaaaaac

比这慢:

aaaaaa(b|c)

当然,如果单独运行它们会慢得多。

优化正则表达式本身

您可以将 RegexBuddy 用于这些目的。只需键入一些模式和源代码,您就会看到正则表达式的所有回溯和耗时部分。您可以更改模式的结构或在您的正则表达式中添加 if-clause 以阻止回溯。

例如,当您知道模式的某些部分只能在某些情况下匹配时,您可以过滤案例:

(?(?=/*fast to check condition*/)/*complex regex here*/|/*simple regex here*/)

预编译模式将它们从本地范围扔到全局范围(使它们成为静态)并添加 RegexOptions.Compiled 选项。

【讨论】:

  • 正确:对于一个过于宽泛的问题来说,答案过于宽泛。
  • 组合正则表达式不起作用,因为实际内容完全不同,我想将每个匹配项链接到某个组。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-10-03
  • 1970-01-01
  • 2010-11-07
  • 1970-01-01
  • 1970-01-01
  • 2013-06-30
  • 1970-01-01
相关资源
最近更新 更多