搜索大文本文件

问题描述 投票:0回答:5

我正在尝试优化大型文本文件(300-600mb)中字符串的搜索。使用我目前的方法,花费的时间太长了。

目前我一直在使用

IndexOf
来搜索字符串,但是为字符串的每一行建立索引所需的时间太长(20 秒)。

如何优化搜索速度?我已经尝试过

Contains()
,但这也很慢。有什么建议么?我正在考虑正则表达式匹配,但我认为这没有显着的速度提升。也许我的搜索逻辑有缺陷

示例

while ((line = myStream.ReadLine()) != null)
{
    if (line.IndexOf(CompareString, StringComparison.OrdinalIgnoreCase) >= 0)
    {
        LineIndex.Add(CurrentPosition);
        LinesCounted += 1;
    }
}
c# performance search io full-text-search
5个回答
12
投票

您使用的强力算法在 O(nm) 时间内执行,其中 n 是正在搜索的字符串的长度,m 是您要查找的子字符串/模式的长度。您需要使用字符串搜索算法

但是,使用精心设计的正则表达式可能就足够了,具体取决于您要查找的内容。请参阅 Jeffrey 的 Friedl 的著作,掌握正则表达式,以获取有关构建高效正则表达式的帮助(例如,无回溯)。

您可能还想查阅优秀的算法文本。我偏爱 Robert Sedgewick 的 算法各种化身[C|C++|Java] 中的算法


5
投票

不幸的是,我不认为直接用 C# 可以做很多事情。

我发现 Boyer-Moore 算法对于这项任务来说非常快。但我发现没有办法做到像

IndexOf
那么快。我的假设是,这是因为
IndexOf
是在手动优化的汇编程序中实现的,而我的代码是在 C# 中运行的。

您可以在文章Fast Text Search with Boyer-Moore中看到我的代码和性能测试结果。


1
投票

您看过这些问题(和答案)吗?

如果您只想读取文本文件,那么按照现在的方式进行操作似乎是正确的方法。其他想法:

  • 如果可以对数据进行预排序(例如将其插入文本文件时),那可能会有所帮助。

  • 您可以将数据插入数据库并根据需要进行查询。

  • 您可以使用哈希表


1
投票

您可以使用regexp.Match(String)。正则表达式匹配速度更快。

静态无效Main()

{

  string text = "One car red car blue car";
  string pat = @"(\w+)\s+(car)";

  // Instantiate the regular expression object.
  Regex r = new Regex(pat, RegexOptions.IgnoreCase);

  // Match the regular expression pattern against a text string.
  Match m = r.Match(text);
  int matchCount = 0;
  while (m.Success) 
  {
     Console.WriteLine("Match"+ (++matchCount));
     for (int i = 1; i <= 2; i++) 
     {
        Group g = m.Groups[i];
        Console.WriteLine("Group"+i+"='" + g + "'");
        CaptureCollection cc = g.Captures;
        for (int j = 0; j < cc.Count; j++) 
        {
           Capture c = cc[j];
           System.Console.WriteLine("Capture"+j+"='" + c + "', Position="+c.Index);
        }
     }
     m = m.NextMatch();
  }

}


1
投票

当我搜索带有 c# 标签的“搜索大文本文件”时,这篇文章是 stackoverflow 上最热门的文章。尽管问题仍然存在,但自这篇文章最初发布以来,有些事情已经发生了变化。比如 300-600 MB 不再被视为大文件,并且 System.Text.RegularExpressions.Regex 的性能得到极大提高。由于这些原因,我觉得更新答案是公平的。

简而言之,使用当前版本的 dotnet 中的

System.Text.RegularExpressions.Regex
对于您能想到的任何搜索都将非常快。速度真的变快了

从 .NET7 开始,Regex 根据实例化方式合并了 4 个不同的引擎。这些引擎提供了高度优化的搜索,“在许多情况下,除了最极端的情况外,它最终在所有情况下都明显优于 Boyer-Moore。”

使用

RegexOptions.Compiled
GeneratedRegex
的 4 个引擎将生成最快的代码(即最好的最佳情况性能)。对于大多数情况,这是一个很好的解决方案。

但是,如果您的用例需要最大稳定性或容易受到输入滥用的影响,那么使用

RegexOptions.NonBacktracking
将通过切换到基于有限自动机的引擎来提供“最佳最坏情况性能”,“以换取降低的最佳情况性能”这“保证它只会对输入中的每个字符执行摊销恒定量的工作。”

这里是 Stephen Toub 的完整博客,介绍了 .NET7 中正则表达式中添加的许多令人印象深刻的优化。

要通过并行性进一步提高

System.Text.RegularExpressions.Regex
的性能或处理超出 RAM 的文件,您可能还想看看 Gigantor

© www.soinside.com 2019 - 2024. All rights reserved.