解析文件中文本的代码减慢到停止c#

时间:2011-09-20 23:52:21

标签: c# regex file-io profiling

 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);

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

大多数文件的时间不到30毫秒,但有些则为11251毫秒。

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

3 个答案:

答案 0 :(得分:2)

我认为目前的违规行为是正则表达式的一部分:

(\w+\.?)*

删除?并添加\w*,您将匹配所有相同的字符串,但效率更高。

(\w+\.?)*可以通过多种不同方式匹配asdf

  • ASDF
  • ASD,F
  • 如,d,F
  • A,S,d,F
  • 一个,SD,F
  • A,S,DF
  • 一个,SDF
  • 如,DF

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

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

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

尝试使用:

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

答案 1 :(得分:2)

尝试简化正则表达式:

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

更新:如果您想要匹配示例,请在结尾处删除分号。

答案 2 :(得分:1)

一些事情:

  1. 取出DiscardBufferedData调用。你不需要它,而且 它的价格昂贵。
  2. 修复双重处理。请注意,也关闭 调用Dispose,所以你也可以摆脱它。
  3. 实际上,有一个 可以用来摆脱的File.ReadAllText方法 您正在构建和处理的StreamReader。