C# 正则表达式性能下降

C# 正则表达式性能下降,c#,regex,performance,C#,Regex,Performance,我正在编写一个C#应用程序,在大量(约2500万)字符串上运行大量正则表达式(~10)。我确实试过用谷歌搜索这个,但是任何带有“减慢”的正则表达式的搜索都充满了关于反向引用等如何减慢正则表达式的教程。我假设这不是我的问题,因为我的正则表达式开始时很快也很慢 对于前一百万个左右的字符串,每1000个字符串大约需要60毫秒来运行正则表达式。到最后,速度会减慢到大约600毫秒。有人知道为什么吗 更糟糕的是,我通过使用RegEx的实例来改进它,而不是使用缓存版本,并尽可能编译表达式 我的一些正则表达式需

我正在编写一个C#应用程序,在大量(约2500万)字符串上运行大量正则表达式(~10)。我确实试过用谷歌搜索这个,但是任何带有“减慢”的正则表达式的搜索都充满了关于反向引用等如何减慢正则表达式的教程。我假设这不是我的问题,因为我的正则表达式开始时很快也很慢

对于前一百万个左右的字符串,每1000个字符串大约需要60毫秒来运行正则表达式。到最后,速度会减慢到大约600毫秒。有人知道为什么吗

更糟糕的是,我通过使用
RegEx
的实例来改进它,而不是使用缓存版本,并尽可能编译表达式

我的一些正则表达式需要改变,例如,取决于可能的用户名
mike said(\w*)
john said(\w*)

我的理解是不可能编译这些正则表达式并传入参数(例如
saidRegex.Match(inputString,userName)

有人有什么建议吗


[编辑以准确反映速度-是每1000个字符串,而不是每字符串]

这可能不是您关于RegEx性能下降问题的直接答案,这有点令人着迷。然而,在阅读了上述所有评论和讨论之后,我建议如下:

解析数据一次,将匹配的数据拆分为数据库表。看起来您正在尝试捕获以下字段:

Player_Name | Monetary_Value
如果您要创建一个每行包含这些值的数据库表,然后在创建新行时捕获每一行—解析它—并附加到数据表—您可以轻松地对数据进行任何类型的分析/计算—而无需反复解析2500万行(这是一种浪费)

此外,在第一次运行时,如果要将25M条记录分解为100000条记录块,然后运行算法250次(100000 x 250=25000000)-您可以享受您描述的所有性能,而不会减慢速度,因为您正在将作业分块

换句话说,请考虑以下内容:

  • 按如下方式创建数据库表:

    CREATE TABLE PlayerActions (
        RowID          INT PRIMARY KEY IDENTITY,
        Player_Name    VARCHAR(50) NOT NULL,
        Monetary_Value MONEY       NOT NULL
    )
    
  • 创建一个算法,将2500万行分解为10万个块。使用LINQ/EF5作为假设的示例

    public void ParseFullDataSet(IEnumerable<String> dataSource) {
        var rowCount = dataSource.Count();
        var setCount = Math.Floor(rowCount / 100000) + 1;
    
        if (rowCount % 100000 != 0)
            setCount++;
    
        for (int i = 0; i < setCount; i++) {
            var set = dataSource.Skip(i * 100000).Take(100000);
            ParseSet(set);
        }
    }
    
    public void ParseSet(IEnumerable<String> dataSource) {
        String playerName = String.Empty;
        decimal monetaryValue = 0.0m;
    
        // Assume here that the method reflects your RegEx generator.
        String regex = RegexFactory.Generate();
    
        for (String data in dataSource) {
            Match match = Regex.Match(data, regex);
            if (match.Success) {
                playerName = match.Groups[1].Value;
    
                // Might want to add error handling here.
                monetaryValue = Convert.ToDecimal(match.Groups[2].Value);
    
                db.PlayerActions.Add(new PlayerAction() {
                    // ID = ..., // Set at DB layer using Auto_Increment
                    Player_Name = playerName,
                    Monetary_Value = monetaryValue
                });
                db.SaveChanges();
    
                // If not using Entity Framework, use another method to insert
                // a row to your database table.
            }
        }
    }
    
    public void ParseFullDataSet(IEnumerable数据源){
    var rowCount=dataSource.Count();
    var setCount=数学楼层(行数/100000)+1;
    如果(行数%100000!=0)
    setCount++;
    对于(int i=0;i
  • 运行上述一次以加载所有预先存在的数据

  • 在某个地方创建一个钩子,它允许您检测新行的添加。每次创建新行时,调用:

    ParseSet(new List<String>() { newValue });
    
    ParseSet(newlist(){newValue});
    
    或者,如果一次创建多个,请调用:

    ParseSet(newValues); // Where newValues is an IEnumerable<String>
    
    ParseSet(newValues);//其中newValues是IEnumerable
    

  • 现在,您可以从数据中执行任何您想要的计算分析或数据挖掘,而不必担心动态超过2500万行的性能。

    Regex确实需要时间进行计算。但是,您可以使用一些技巧使其紧凑。 也可以在C#中使用字符串函数来避免正则表达式函数

    代码会很长,但可能会提高性能。 String有几个函数可以剪切和提取字符,并根据需要进行模式匹配。 例如:IndeOfAny,LastIndexOf,Contains

    string str= "mon";
    string[] str2= new string[] {"mon","tue","wed"};
    
    if(str2.IndexOfAny(str) >= 0)
    {
      //success code//
    }
    

    你能发布一些代码吗?如果你已经采取了通常的措施来提高性能,那么很难给出更多的建议。如果可以的话,你能展示你的正则表达式吗?正则表达式引擎本身不太可能减速。更有可能的情况是,您的应用程序正在保存结果,因此内存正在增长,这会导致总体性能下降。监视进程内存大小。还要检查内存泄漏。另外,您如何确定正则表达式本身是慢度的根源?您是否在循环中做了其他可能也要受到责备的事情,例如检索“当前”字符串等?我正在检索当前字符串,这让我很痛苦。我不再做了。我正在存储结果,但当我运行性能分析器时,它仍然指责正则表达式是最严重的违规者。给我一点时间,我会发布一些删除了识别内容的正则表达式。谢谢你的快速回复!注意:上面的代码是在没有编译的情况下编写的——因此我不能保证它能按原样工作,但是如果您选择实现所描述的解决方案,它应该会引导您正确的方向。