代码之家  ›  专栏  ›  技术社区  ›  Ash Burlaczenko

你怎么知道的字符串。包含工作?[副本]

  •  8
  • Ash Burlaczenko  · 技术社区  · 15 年前

    可能重复:
    What algorithm .Net use for searching a pattern in a string?

    我的程序中有一个循环,从文件中获取一行。然后检查行是否包含字符串

    if(line.Contains("String"))
    {
        //Do other stuff
    }
    

    文件中有超过200万行,因此如果我能将速度加快1/10毫秒,那么每次运行都可以节省我超过3分钟的时间。

    所以。。。假设一行有1000个字符长,那么查找短字符串或长字符串是更快,还是没有区别?

    line.Contains("ABCDEFGHIJKLMNOPQRSTUVWXYZ");
    

    line.Contains("ABCDEFG")
    

    先谢谢你。

    7 回复  |  直到 9 年前
        1
  •  24
  •   Hans Passant    15 年前

    字符串。包含()走了一条痛苦的道路System.Globalization.CompareInfo比较信息进入CLR和NLS支持子系统,我彻底迷路了。它包含高度优化的代码,具有令人印象深刻的性能。唯一的方法是通过pinvoking的标准CRT功能wcsstr,可在msvcrt.dll

        [DllImport("msvcrt.dll", CharSet = CharSet.Unicode)]
        private static extern IntPtr wcsstr(string toSearch, string toFind);
    

    它回来了积分零点如果找不到字符串。我做了一些测量,用字符串.IndexOf()而不是Contains()来测试各种字符串比较选项。所有时间都以纳秒为单位,在60个字符的字符串中搜索7个字符的字符串。在不存在字符串的情况下,测量最坏情况。使用20个样本中的最低时间:

    StringComparison.Ordinal (same as Contains) : 245 nanoseconds
    StringComparison.OrdinalIgnoreCase : 327
    StringComparison.InvariantCulture : 251
    StringComparison.InvariantCultureIgnoreCase : 327
    StringComparison.CurrentCulture : 275
    StringComparison.CurrentCultureIgnoreCase : 340
    wcsstr : 213
    

        3
  •  3
  •   AnthonyLambert    15 年前

    如果.NET字符串。包含使用 Boyer-Moore algorithm 搜索更长的字符串更快。

    我建议您,如果您正在读取一个带分隔符的文件,例如,每行都是一系列由逗号分隔的文本字段,如果您知道行中的位置0不能在字符40之前,那么您可以通过不从该位置0进行搜索来节省一些搜索时间。

    在分隔符字符上使用String Spilt函数分割一行是很常见的这将返回一个字符串数组。然后您将只在该值可能出现的字段中进行搜索。这也会更快。

        4
  •  1
  •   Ben McCormack    15 年前

    当谈到提高性能时,您需要确保您想要改进的内容实际上是瓶颈的原因。我将首先分析代码中各个部分的性能,并找出哪一部分引入了最大的瓶颈。

    乍一看,我认为这个过程的三个主要组成部分值得分析:

    • 循环浏览文件的整个内容(这可能包括也可能不包括文件IO注意事项,您可能希望单独进行测试)。
    • 检查 String.Contains() 对于文件中的每一行。
    • 有比赛的时候要“做事”

    虽然有很多优秀的商业剖析器,但是您可以从使用一个简单的计时器开始(比如 System.Diagnostics.Stopwatch

    1. 测量只需浏览整个文件而不做任何其他操作所需的时间。这将隔离循环和IO代码,以便查看它的性能。
    2. String.Contains
    3. 最后,添加“dostuff”代码,并使用添加的代码测量总时间。

    Test           Total Time   Cost (Difference)
    =============================================
    Do Nothing     0s           0s
    Loop Only      100s         100s
    Add Comparison 105s         5s
    Add Do Stuff   130s         25s
    

    看看这些(假的)数字,这个过程中最昂贵的部分是循环和IO代码,所以我将从这里开始尝试提高性能。由于“Do Stuff”部分增加了25秒的总执行时间,因此我接下来会查看该代码,看看是否有什么可以改进的地方。最后,我看一下字符串比较。

    第一 .

        5
  •  1
  •   JulianR    15 年前

    Regex 实际上比 Contains . 当然,只有在多次搜索同一个字符串时,编译成本才是值得的。但如果是这样,速度就快了两倍多。你自己试试:

    static void Test()
    {
      var random = new Random(10);
    
      var alphabet = "abcdefghijklmnopqrstuvwxyz";
      var content = new String((from x in Enumerable.Range(0, 10000000)
                                select a[random.Next(0, a.Length)]).ToArray());
    
      var searchString = content.Substring(5000000, 4096);
    
      var regex = new Regex(searchString);
    
      var sw = Stopwatch.StartNew();
      for (int i = 0; i < 1000; i++)
      {
        if (!regex.IsMatch(content))
        {
          throw new Exception();
        }
      }
    
      sw.Stop();
      Console.WriteLine("Regex: " + sw.Elapsed);
      sw.Restart();
    
      for (int i = 0; i < 1000; i++)
      {
        if (!content.Contains(searchString))
        {
          throw new Exception();
        }
      }
      sw.Stop();
      Console.WriteLine("String.Contains: " + sw.Elapsed);
    
    }
    

    怎样 它可以这么快,看看编译后的程序集,它是一个混乱的混乱 switch 声明。但是很快, 快。

        6
  •  0
  •   Adi_aks    15 年前

    这个字符串。包含方法在且仅当此字符串包含指定的字符值序列时返回true。

    它基本上用于检查字符串中的子字符串。

    http://csharp.net-informations.com/string/csharp-string-contains.htm

        7
  •  0
  •   annakata    15 年前

    Contains InternalFindNLSStringEx