vb.net Regex Повышение производительности с помощью компиляции и общих переменных - PullRequest
1 голос
/ 30 сентября 2011

Я пишу некоторый код, который использует фиксированные регулярные выражения для поиска строк и сопоставления с образцом.

Это просто, но я хочу улучшить производительность регулярных выражений с помощью компиляции (это сайт с высоким трафиком).

Я думал о том, чтобы скомпилировать регулярное выражение и поместить его в общую (статическую) переменную внутри класса.

Примерно так:

Namespace Regexs

    Public Class UrlNickname

        Private Shared rgx As Regex = New Regex("^\/\w{4,20}$", RegexOptions.IgnoreCase Or RegexOptions.CultureInvariant Or RegexOptions.Compiled)

        ''' <summary>
        ''' Returns a Nickname string if pattern found in Url, otherwise returns Empty string.
        ''' </summary>
        ''' <param name="url">The Url string to search.</param>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Shared Function ContainsNickname(url As String) As String
            If rgx.IsMatch(url) Then
                Return url.Substring(1, url.Length - 1)
            End If
            Return String.Empty
        End Function

    End Class

End Namespace

Тогда вы можете использовать такую ​​функцию:

Dim url As String = HttpContext.Current.Request.RawUrl

Dim nickname As String = Regexs.UrlNickname.ContainsNickname(url)
If Not String.IsNullOrEmpty(nickname) Then
    //nickname pattern match found:
    //do something like RedirectToRoutePermanent
End If

По сути, я храню регулярное выражение в общей (статической) переменной, чтобы она компилировалась только один раз.

Затем будет вызвана функция, чтобы проверить, было ли найдено соответствие шаблону имени пользователя на странице ошибки 404.

Какой это лучший подход для улучшения производительности регулярных выражений?

Примечание: я не заинтересован в решении проблемы с ошибкой на странице 404 выше, это просто простой пример.


Дальнейшие достижения могут затем использовать общий общий список регулярных выражений, например:

Private Shared _rgxList As List(Of Regex)

Public Sub New()
    //get list of regex expressions from database and populate:
    _rgxList.Add(New Regex("blah", RegexOptions.Compiled))
    _rgxList.Add(New Regex("blah2", RegexOptions.Compiled))

Public Shared Function IsMatch(str) as Boolean
    With each reg in _rgxList
        return reg.IsMatch(str)

New () будет вызываться для события Application.Start.

1 Ответ

0 голосов
/ 30 сентября 2011

выглядит хорошо.Кроме того, я бы сделал переменную Shared ReadOnly, чтобы избежать случайных изменений.

Обратите внимание, однако, что компиляция регулярных выражений увеличивает производительность примерно на 30% во время выполнения, но также имеет свои недостатки, вВ частности, это требует больше памяти.Хорошее сравнение можно найти здесь:

Итак, нет общего "А лучшечем B "ответить здесь.Все зависит от ваших точных требований.Возможно, вам придется выполнить измерения, чтобы выяснить, что работает лучше в вашем конкретном случае.

Общие рекомендации по настройке производительности : убедитесь, что что-то действительно является узким местом производительности прежде чем его улучшить.Не имеет значения, занимает ли ваше регулярное выражение 0,01 или 0,02 секунды, если, например, поиск псевдонима в базах данных занимает 2 секунды.Используйте встроенные инструменты из .net Framework (например, Класс секундомера ) или внешние инструменты (например, EQATEC Profiler ), чтобы определить узкие места.

...