天天看點

一起談.NET技術,RegexOptions.Compiled的含義和使用

  曾經一位同僚在寫程式時發現在利用正規表達式比對文本時的效率很低。首先可以排除是正規表達式本身的問題,因為所使用的正規表達式是十分簡單的,比對的文本量也不算大。檢查的時候去掉了RegexOptions.Compiled的選項之後,程式整體速度得到了很大的提升。

  這是因為誤解了RegexOptions.Compiled這個選項提供的功能。在正則引擎啟動正規表達式之前,需要做一些準備工作,這些準備工作包括檢查正規表達式是否符合格式規範,并将其轉化能夠實際應用的内部形式。在許多關于正規表達式的文檔中,将這一過程用compile來描述。然而在.NET中,這個過程實際上是以parsing來描述的。

  在.NET中,parsing是指在程式執行過程中,第一次遇到正規表達式時必須檢查它是否格式規範,并将其轉換為适于.NET正則引擎實際應用的内部形式。

  當指定RegexOptions.Compiled的時候,所提供的機制是告訴正則引擎,除了将正規表達式轉換為認定的内部形式外,還将其編譯(很多人會混淆這裡的編譯和parsing的過程)為底層的MSIL(Microsoft Intermediate Language)代碼,在正規表達式實際應用時,可以由JIT(Just-In-Time)優化為更快的本地機器代碼。

  啟動這個選項究竟對性能産生了怎樣的影響,可以從三個方面來看。

  首先在啟動速度上,在不使用RegexOptions.Compiled會比較快,使用了RegexOptions.Compiled情況下,通常會使啟動速度慢許多,據說最多是60倍。

  在記憶體占用方面,使用RegexOptions.Compiled時,通常每個表達式會占用5KB~15KB的記憶體,更重要的是,在程式執行過程中,這塊記憶體是無法被釋放的。這裡有時會帶來一些問題,因為Regex在.NET中作為對象被封裝,如果是多個程序或請求同時調用到這個代碼片段,可能會造成相同的正規表達式在重複占用了記憶體,這取決于程式具體的實作方式。

  在比對速度方面,RegexOptions.Compiled是可以提升比對速度的,但是因為有在啟動速度和記憶體占用方面帶來的額外開銷,是以除非是在需要比對大量的文本和反複使用某正規表達式時,這種提升非常不明顯,而且在許多人誤用此選項的情況下,得到的結果反而是程式整體運作速度的下降。是以在非大量文本處理的情況下,如果對程式整體效率有嚴格要求,建議不要使用該選項。

  如果需要使用該選項,那麼一個應該考慮的也是更好的方案應該是将要使用的正則對象封裝到一個DLL中,這将使最終的程式占用的記憶體更少,因為不必裝載使用RegexOptions.Compiled編譯正規表達式的包。另外,由于在封裝DLL時正規表達式已經編譯好了,裝載的速度也就得到了提升。附帶的一個好處就是這個包還可以提供給其他需要的程式員調用,而不是copy正規表達式的代碼。

  以上内容和分析适用于.NET Framework 2.0。

繼續閱讀