2011-09-20 49 views
4
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撕裂就好了然后爬行。我正在分析代码,但想知道是否有什么明显的我做错了。用于解析文件内文本的代码减速停止c#

的正则表达式是

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

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

大多数文件需要少于30毫秒,但有些是11251毫秒。

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

+1

Close和Dispose不等价,通常Dispose也调用close,就像SqlConnection一样,但这并不意味着它们是等价的,因为Close永不处理(或者至少通常不会)。 –

+0

@Davide我注意到perf命中后添加了那些乐趣。由于使用声明,我可能会删除这些行。我将不得不检查文件vcsjones,看看我能否注意到一些事情。 – Steve

+0

@Davide:从StreamReader.Close上的MSDN:“Close的这个实现调用Dispose方法传递一个真实值。” – Joe

回答

2

尽量简化你的正则表达式:

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

UPDATE:那么,在年底,如果你想匹配您的例子删除分号。

+0

实际上它确实匹配。只是意识到我并不总是有一个;因为js不需要这样添加;?固定的。 – Steve

+0

@Steve是的,';?'应该主要解决你自己的性能增益问题。因为只有在非可选';'的原始正则表达式失败时,才会对性能产生影响。 –

+0

@JacobEggers所以;;?会毁了货?有更好的选择吗? – Steve

1

有几件事情:

  1. 取出DiscardBufferedData电话。你不需要它,而且它很昂贵。
  2. 修复双重配置。请注意,关闭也叫 调用Dispose,所以你可以摆脱这一点。
  3. 实际上,有一个 File.ReadAllText方法,可用于摆脱您正在构建和处理的 StreamReaders。
+0

删除了这些调用,并切换到File.ReadAllText - 这给了巨大的性能增益。对于一些相对不复杂的文件,速度会变慢。它必须是我必须假定的正则表达式的东西? – Steve

+0

在这一点上,我认为你正在做的分析将有助于缩小分析范围。可能是正则表达式,可能是关于那个文件的东西,可能是在那个时候做垃圾收集的终结器线程 - 很难说。 – Joe

2

我认为目前的违规一块一块是这里的正则表达式:

(\w+\.?)* 

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

(\w+\.?)*可以匹配asdf许多不同的方式:

  • ASDF
  • ASD中,f
  • 如,d,F
  • A,S,d,F
  • 一个,SD, f
  • a,s,df
  • a,sdf
  • 如,DF

我猜,你的一些文件中有这样的一堆线:

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

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

尝试使用:

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

我还建议使用'RegexOptions.ExplicitCapture',因为Regex中没有任何组被引用。 –

+0

与dojo.require('dijit.form.Button')不匹配 dojo.require('dijit.form'); dojo.require('ijit.widgets.upload.FileUpload') – Steve

+0

为什么不只是做'[\ w \。] +' –