解析文件中的文本的代码在c#中会减慢到一半

本文关键字:一半 代码 文件 文本 | 更新日期: 2023-09-27 18:09:05

 private static void BuildDictionaryOfRequires(Regex exp, Dictionary<string, string> dictionary, DirectoryInfo dir)
    {
        var i = 0;
        var total = dir.EnumerateFiles("*.*", SearchOption.AllDirectories).
                                 Where(x => x.Extension == ".aspx" || x.Extension == ".ascx").Count();
        foreach (var item in dir.EnumerateFiles("*.*", SearchOption.AllDirectories).
                                 Where(x => x.Extension == ".aspx" || x.Extension == ".ascx"))
        {
 #if DEBUG
            Stopwatch sw = Stopwatch.StartNew();
 #endif
            var text = File.ReadAllText(item.FullName);
            MatchCollection matches = exp.Matches(text);
            foreach (Match match in matches)
            {
                var matchValue = match.Groups[0].Value;
                if (dictionary.ContainsKey(matchValue))
                {
                    dictionary[matchValue] = string.Format("{0},{1}", dictionary[matchValue], item.Name);
                }
                else
                {
                    dictionary.Add(matchValue, item.Name);
                }
            }
            Console.WriteLine(string.Format("Found matches in {0}.", item.Name));
 #if DEBUG
            sw.Stop();
            Console.WriteLine("Time used (float): {0} ms", sw.Elapsed.TotalMilliseconds);
 #endif

            Console.WriteLine(string.Format("{0} of {1}", (++i).ToString(), total));
        }
    }

, lambda找到大约232个文件。它通过了160英里,然后就开始爬行了。我现在正在分析代码,但想知道是否有什么明显的我做错了。

正则表达式是

    Regex exp = new Regex(@"dojo'.require'([""']['w'.]+['""]');?", RegexOptions.IgnoreCase | RegexOptions.Compiled);

所有的文件长度和结构相似。

大多数文件占用不到30ms,但有些文件占用11251 ms。

使用更新的正则表达式,整个过程现在需要1700ms。唷!

解析文件中的文本的代码在c#中会减慢到一半

尝试简化你的正则表达式:

Regex exp = new Regex(@"dojo'.require'([""']['w'.]+[""']')", RegexOptions.IgnoreCase | RegexOptions.Compiled);

UPDATE:如果您想匹配您的示例,则删除末尾的分号

我认为当前有问题的部分是这里的正则表达式:

('w+'.?)*

去掉?然后加上'w*,你将匹配所有相同的字符串,但效率更高。

('w+'.?)*可以通过多种方式匹配asdf:

  • asdf
  • asd, f
  • , d, f
  • a, s, d, f
  • , sd, f
  • a, s, df
  • ,自卫队
  • , df

我猜你的一些文件有一堆这样的行:

dojo.require('asdf')  //with no ;

你的正则表达式将失败的最贪婪的匹配,然后尝试每一个其他的组合,直到它最终没有得到任何匹配。随着'asdf'字符串的增长,这会变得非常昂贵。

尝试使用:

Regex exp = new Regex(@"dojo'.require'(('""|'')(('w+'.)*'w*)('""|'')');");

几点:

  1. 取出DiscardBufferedData调用。你不需要它,而且它是昂贵的。
  2. 修复双重处置。请注意Close也调用Dispose,所以你也可以摆脱那个。
  3. 事实上,有文件。ReadAllText方法,可以用来摆脱你正在构建和处理的流阅读器。