2013-05-29 21 views
1

我有兩個文本框,一個用於輸入,另一個用於輸出。我需要從輸入中僅過濾十六進制字符並以大寫形式輸出它。我檢查過使用正則表達式(Regex)比使用循環要快得多。哪些正則表達式和上面的組合更快?

我當前的代碼以第一大寫然後過濾16進制數如下:

string strOut = Regex.Replace(inputTextBox.Text.ToUpper(), "[^0-9^A-F]", ""); 
outputTextBox.Text = strOut; 

一種可替換地:

string strOut = Regex.Replace(inputTextBox.Text, "[^0-9^A-F^a-f]", ""); 
outputTextBox.Text = strOut.ToUpper(); 

該輸入可以包含多達32k的字符,因此速度是重要的在這裏。我用TimeSpan來衡量,但結果不一致。

我的問題是:哪些代碼具有更好的高速性能,爲什麼?

+1

使用'秒錶'。 – SLaks

+0

你是否確信這不是過早優化的情況?你是否期望文本框被填充每秒超過1000次的32K字符? – HABO

回答

3

這絕對是過早優化的情況下:32K字是不是什麼大不了的現代計算機上運行的微調正則表達式引擎,所以這個優化任務主要是理論上的。

在討論性能之前,值得指出的是表達式可能不是您想要的,因爲它們允許輸入^個字符。您需要改用[^0-9A-F][^0-9A-Fa-f]

兩個正則表達式的速度將是相同的,因爲字符在字符類的數量幾乎沒有有差別。但是,將調用第二個組合ToUpper調用可能較短的字符串,因爲所有無效字符都將被刪除。因此,第二種選擇可能會稍微快一點。但是,如果必須將其優化爲最後一個CPU週期,則可以在不使用正則表達式的情況下重寫此操作,以避免ToUpper中的內存分配:循環遍歷輸入字符串,並將所有有效字符添加到StringBuilder中作爲你走。當您看到小寫字符時,請將其轉換爲大寫字母。

+0

「字符類中的字符數量幾乎沒有區別」請閱讀http://stackoverflow.com/questions/16621738/d-is-less-efficient-than-0-9,全部原因'\ d'慢於'[0-9]'是因爲它包含更多字符。 – AJMansfield

+0

@AJMansfield這不是因爲'\ d'只是有更多的字符,而是因爲代碼點分散得太多了。但是,在這種情況下,字符彼此靠近,所以額外的小寫字符檢查時間不會太長。 – dasblinkenlight

+0

好的,我明白你的意思了。另外,如果你真的需要優化它,你應該爲GPU優化它,而不是標準的CPU。 – AJMansfield

1

是很簡單的測試:

using System; 
using System.Diagnostics; 
using System.Linq; 
using System.Text.RegularExpressions; 

namespace ConsoleApplication1 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      string letters = "abcdefghijklmnopqrstuvxyzABCDEFGHIJKLMNOPQRSTUVXYZ"; 
      Random random = new Random(); 
      string[] strings = Enumerable.Range(0, 5000).Select(i1 => string.Join("", Enumerable.Range(0,32000).Select(i2 => letters[random.Next(0, letters.Length - 1)]))).ToArray(); 

      Stopwatch stopwatchA = new Stopwatch(); 
      stopwatchA.Start(); 

      foreach (string s in strings) 
       Regex.Replace(s.ToUpper(), "[^0-9^A-F]", ""); 

      stopwatchA.Stop(); 

      Stopwatch stopwatchB = new Stopwatch(); 
      stopwatchB.Start(); 

      foreach (string s in strings) 
       Regex.Replace(s, "[^0-9^A-F^a-f]", "").ToUpper(); 

      stopwatchB.Stop(); 

      Debug.WriteLine("stopwatchA: {0}", stopwatchA.Elapsed); 
      Debug.WriteLine("stopwatchB: {0}", stopwatchB.Elapsed); 
     } 
    } 
} 

運行1:

stopwatchA:00:00:39.6552012

stopwatchB:00:00:40.6757048

運行2 :

stopwatchA:00:00:39.7022437

stopwatchB:00:00:41.3477625

在那些運行時,第一種方法是更快。

+0

這不是一個好的基準,因爲沒有東西會被拋棄:兩個表達式都通過了所有的東西。您需要將相當數量的非字母添加到混合中,然後查看兩個表達式之後的比較方式。 – dasblinkenlight

+0

dasblinkenlight:表達式僅傳遞這些內容以替換爲空字符串:ghijklmnopqrstuvxyzGHIJKLMNOPQRSTUVXYZ – lightbricko

0

在理論尺寸上,string.ToUpper()可能會分配一個新字符串(請記住,.NET字符串在語義上是不可變的),但是正則表達式可以節省內存,即在一般情況下它應該更快字符串)。如果使用toUpper()調用,輸入字符串將循環兩次。