2012-04-09 26 views
7

我正在使用以下代碼來測試編譯正則表達式的CompileToAssembly性能,但結果不合適。請讓我知道我錯過了什麼。謝謝!!!爲什麼Regex CompileToAssembly的性能比編譯正則表達式和解釋正則表達式慢?

static readonly Regex regex = new Regex(@"(stats|pause\s?(all|\d+(\,\d+)*)|start\s?(all|\d+(\,\d+)*)|add\s?time\s?(all|\d+(\,\d+)*)(\s\d+)|c(?:hange)?\s?p(?:asskey)?|close)(.*)", RegexOptions.Compiled); 
static readonly Regex reg = new Regex(@"(stats|pause\s?(all|\d+(\,\d+)*)|start\s?(all|\d+(\,\d+)*)|add\s?time\s?(all|\d+(\,\d+)*)(\s\d+)|c(?:hange)?\s?p(?:asskey)?|close)(.*)"); 
static readonly Regex level4 = new DuplicatedString(); 

    static void Main() 
    { 
     const string str = "add time 243,3453,43543,543,534534,54534543,345345,4354354235,345435,34543534 6873brekgnfkjerkgiengklewrij"; 
     const int itr = 1000000; 
     CompileToAssembly(); 
     Match match; 
     Stopwatch sw = new Stopwatch(); 
     sw.Start(); 
     for (int i = 0; i < itr; i++) 
     { 
      match = regex.Match(str); 
     } 
     sw.Stop(); 
     Console.WriteLine("RegexOptions.Compiled: {0}ms", sw.ElapsedMilliseconds); 

     sw.Reset(); 
     sw.Start(); 
     for (int i = 0; i < itr; i++) 
     { 
      match = level4.Match(str); 
     } 
     sw.Stop(); 

     Console.WriteLine("CompiledToAssembly: {0}ms", sw.ElapsedMilliseconds); 

     sw.Reset(); 
     sw.Start(); 
     for (int i = 0; i < itr; i++) 
     { 
      match = reg.Match(str); 
     } 
     sw.Stop(); 
     Console.WriteLine("Interpreted: {0}ms", sw.ElapsedMilliseconds); 
     Console.ReadLine(); 
    } 

    public static void CompileToAssembly() 
    { 
     RegexCompilationInfo expr; 
     List<RegexCompilationInfo> compilationList = new List<RegexCompilationInfo>(); 

     // Define regular expression to detect duplicate words 
     expr = new RegexCompilationInfo(@"(stats|pause\s?(all|\d+(\,\d+)*)|start\s?(all|\d+(\,\d+)*)|add\s?time\s?(all|\d+(\,\d+)*)(\s\d+)|c(?:hange)?\s?p(?:asskey)?|close)(.*)", 
        RegexOptions.Compiled, 
        "DuplicatedString", 
        "Utilities.RegularExpressions", 
        true); 
     // Add info object to list of objects 
     compilationList.Add(expr); 

     // Apply AssemblyTitle attribute to the new assembly 
     // 
     // Define the parameter(s) of the AssemblyTitle attribute's constructor 
     Type[] parameters = { typeof(string) }; 
     // Define the assembly's title 
     object[] paramValues = { "General-purpose library of compiled regular expressions" }; 
     // Get the ConstructorInfo object representing the attribute's constructor 
     ConstructorInfo ctor = typeof(System.Reflection.AssemblyTitleAttribute).GetConstructor(parameters); 
     // Create the CustomAttributeBuilder object array 
     CustomAttributeBuilder[] attBuilder = { new CustomAttributeBuilder(ctor, paramValues) }; 

     // Generate assembly with compiled regular expressions 
     RegexCompilationInfo[] compilationArray = new RegexCompilationInfo[compilationList.Count]; 
     AssemblyName assemName = new AssemblyName("RegexLib, Version=1.0.0.1001, Culture=neutral, PublicKeyToken=null"); 
     compilationList.CopyTo(compilationArray); 
     Regex.CompileToAssembly(compilationArray, assemName, attBuilder); 
    } 

以下是結果:

RegexOptions.Compiled: 3908ms 
CompiledToAssembly: 59349ms 
Interpreted: 5653ms 
+2

我只是自己運行代碼。這是我的結果:'RegexOptions.Compiled:8399ms'; 'CompiledToAssembly:7806ms'; '解釋:10405ms'。正是我所期望的。 – mellamokb 2012-04-09 22:03:39

+1

在調試模式下再次嘗試在Visual Studio中獲得大致相同的結果。你正在分別調用'CompileToAssembly()',然後運行該部分註釋掉,是否正確? – mellamokb 2012-04-09 22:12:19

+0

我試着運行exe現在的結果是更好的...不知道爲什麼它給我奇怪的結果,當我早些時候嘗試。 Neway仍然結果與theroy不匹配以下是10000000次迭代的結果:RegexOption.Compiled:34413msCompiledToAssembly:37125 Interpreted:47322 ....爲什麼遵守彙編比編譯正則表達式更多的時間? – iRock 2012-04-09 22:17:04

回答

6

你的代碼中有一個問題:靜態字段初始運行靜態方法運行。這意味着level4已在Main()運行之前分配。這意味着level4引用的對象是而不是CompileToAssembly()中創建的類的實例。

請注意,Regex.CompileToAssembly的示例代碼顯示了編譯正則表達式及其在兩種不同程序中的消耗。因此,您計時爲「CompiledToAssembly」的實際正則表達式可能是您在早期測試中編譯的不同正則表達式。

另一個需要考慮的因素是:將程序集加載到內存中並將其加載到機器代碼的開銷可能足夠大,以至於需要超過1,000,000次迭代才能看到好處。

+0

區別是55s!這不是由於一次性加載開銷。看到我的答案。 – usr 2012-04-09 21:01:43

+0

@us,當然,這就是爲什麼我提到它是「考慮的另一個因素」。更重要的因素是OP的示例代碼*沒有對預期的正則表達式進行計時。 – phoog 2012-04-09 21:04:14

+0

與使用compileToAssembly選項時每次匹配所花費的時間相比,已經檢查了將程序集加載到內存中的時間可以忽略不計。此外,嘗試在main()內創建對象不起作用。 – iRock 2012-04-09 21:07:10

4

您正在調試器(Visual Studio)下運行。它會阻止裝載程序集時發生JIT優化。嘗試在沒有調試器的情況下運行(ctrl-f5)。

+0

中創建。試過已經沒有太大的改進:( – iRock 2012-04-09 21:04:13

+1

沒有調試器的情況下運行不會奇蹟般地將'level4'字符串對象轉換爲已編譯的正則表達式。 – Kaz 2012-04-09 21:22:23

+0

正則表達式彙編到前面已經完成了..在這裏顯示瞭如何將它編譯成彙編代碼這不是實際代碼 – iRock 2012-04-09 21:29:52