0

VB.net の正規表現コードは遅いことが知られていますか?

大量のテキスト データを消去していたコードをいくつか引き継ぎました。コードの実行速度はかなり遅かったので、速度を上げる方法を探していました。問題の一部である可能性があると思われる、頻繁に実行されるいくつかの関数を見つけました。

電話番号を消去する元のコードは次のとおりです。

        Dim strArray() As Char = strPhoneNum.ToCharArray
        Dim strNewPhone As String = ""
        Dim i As Integer

        For i = 0 To strArray.Length - 1
            If strArray.Length = 11 And strArray(0) = "1" And i = 0 Then
                Continue For
            End If

            If IsNumeric(strArray(i)) Then
                strNewPhone = strNewPhone & strArray(i)
            End If
        Next

        If Len(strNewPhone) = 7 Or Len(strNewPhone) = 10 Then
            Return strNewPhone
        End If

コードを書き直して、正規表現を使用して配列とループを排除しました。

        Dim strNewPhone As String = ""
        strNewPhone = Regex.Replace(strPhoneNum, "\D", "")
        If strNewPhone = "" OrElse strNewPhone.Substring(0, 1) <> "1" Then
            Return strNewPhone
        Else
            strNewPhone = Mid(strNewPhone, 2)
        End If

        If Len(strNewPhone) = 7 Or Len(strNewPhone) = 10 Then
            Return strNewPhone
        End If

いくつかのテストを実行した後、新しいコードは古いコードよりも大幅に遅くなりました。VB.net の正規表現は遅いですか、問題である他のものを追加しましたか、それとも元のコードはそのままで問題ありませんか?

4

3 に答える 3

3

Visual Studio Profiler でいくつかのテストを実施しましたが、あなたと同じ結果は得られませんでした。数字が で始まっていない場合、長さチェックが失われる原因となった正規表現関数の論理エラーがありました1。テストでそれを修正しました。

  1. 私は自分のテストで、最初と最後に行った関数がペナルティを受けることに気付きました。そのため、各関数を個別に実行し、事前にプライミング関数を実行しました。
  2. テストに応じて、さまざまな長さのパターンのような電話番号を使用して、関数を 10000 回または 100000 回実行しました。どの方法でも同じ数値が得られました。

結果

一般的に、私の方法は常にわずかに高速でした。

  1. 安価なタイマー テストを行ったところ、元の機能は 2 倍遅くなりました。
  2. プロファイラーは、元の方法が私たちの方法よりも約 60% 多くのメモリを使用したことを示しました。
  3. Profiler は、元の方法が機能するのに 8 倍の時間がかかることを示しました。
  4. Profiler は、元の方法が約 40% 多くのプロセッサ サイクルを要したことを示しました。

私の結論

すべてのテストで、元の方法ははるかに遅くなりました。1回のテストでより良い結果が得られていれば、私たちの不一致を説明することができます. これらの方法を完全に分離してテストした場合、同様の方法を思いつくと思います。

私の最善の推測では、他の何かが結果に影響を与えており、元の方法の方が優れているというあなたの評価は間違っていると思います.

あなたの改訂された機能

Function GetPhoneNumberRegex(strPhoneNum As String)
    Dim strNewPhone As String = ""
    strNewPhone = Regex.Replace(strPhoneNum, "\D", "")
    If strNewPhone <> "" And strNewPhone.Substring(0, 1) = "1" Then
        strNewPhone = Mid(strNewPhone, 2)
    End If

    If Len(strNewPhone) = 7 Or Len(strNewPhone) = 10 Then
        Return strNewPhone
    End If

    Return ""
End Function

私の機能

Function GetPhoneNumberMine(strPhoneNum As String)
    Dim strNewPhone As String = Regex.Replace(strPhoneNum, "\D", "")
    If (strNewPhone.Length >= 7 And strNewPhone(0) = "1") Then
        strNewPhone = strNewPhone.Remove(0, 1)
    End If

    Return If(strNewPhone.Length = 7 OrElse strNewPhone.Length = 10, strNewPhone, "")
End Function
于 2013-08-19T19:02:45.520 に答える
1

このようなことを繰り返すと、この状態になると速度が低下します。

 If Len(strNewPhone) = 7 Or Len(strNewPhone) = 10 Then
     Return strNewPhone
 End If

代わりに、これをしてください...

     Dim value = Len(strNewPhone)
     If value = 7 OrElse value = 10 Then
         Return strNewPhone
     End If

ただし、個々の部分 (条件/ステートメント) を測定して、どれが速度を落としているかを判断する必要がありますが、それが本当に重要な場合に限ります。

于 2013-08-19T17:32:02.273 に答える
1

実際の問題が発生しているかどうかはわかりませんが、正規表現は使用するたびに新しくコンパイルされるため、表示されるコードは非常に遅くなる可能性があります。

これがより良いかどうかを確認してください:

Regex rx = new Regex("\D") ' do this once, use it each time

MSDNでの参照

于 2013-08-19T17:32:34.413 に答える