2016-12-29 3 views
2

мне нужно сделать строка заменяет ... Есть только несколько случаев, мне нужно обращаться:Любой способ улучшить Regex.Replace performance?

1) optional case insensitive 
2) optional whole words 

Сейчас я использую _myRegEx.Replace() ... если # 1 указано, я добавьте флаг RegexOptions.IgnoreCase. Если указано # 2, я завершаю поисковое слово в \ b < слово > \ b.

Это прекрасно работает, но его очень медленно. Мой тест занимает 1100 мс против 90 мс с помощью String.Replace. Очевидно, что некоторые проблемы с этим:

1) case insensitive is tricky 
2) regex \b<word>\b will handle "<word>", " <word>", "<word> " and " <word> "... string replace would only handle " <word> ". 

Я уже использую флаг RegexOptions.Compiled.

Любые другие варианты?

+0

@ M.kazemAkhgary, я не использую статический, я использую экземпляр ... Я обновил сообщение, чтобы уточнить. – SledgeHammer

+1

Как вы создаете экземпляр 'Regex'? есть известная медлительность из-за некоторого шаблона регулярного выражения, [например, это] (http://stackoverflow.com/questions/9687596/slow-regex-performance), и даже microsoft дает [наилучшую практику использования 'Regex'] (https://msdn.microsoft.com/en-us/library/gg578045(v=vs.110).aspx). –

+0

@BagusTesa просто что-то простое, как новое Regex ("\ bTest \ b", RegexOptions.Compiled | RegexOptions.IgnoreCase); для случаев 1 и 2. – SledgeHammer

ответ

2

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

Давайте заменим \bfast\b с 12345 в строке в миллион раз, с помощью четырех различных методов и времени, сколько времени это заняло - на двух разных компьютерах:

var str = "Regex.Replace is extremely FAST for simple replacements like that"; 
var compiled = new Regex(@"\bfast\b", RegexOptions.IgnoreCase | RegexOptions.Compiled); 
var interpreted = new Regex(@"\bfast\b", RegexOptions.IgnoreCase); 
var start = DateTime.UtcNow; 
for (int i = 0; i < 1000000; i++) 
{ 
    // Comment out all but one of these: 
    str.Replace("FAST", "12345"); // PC#1: 208 ms, PC#2: 339 ms 
    compiled.Replace(str, "12345"); // 1100 ms, 2708 ms 
    interpreted.Replace(str, "12345"); // 788 ms, 2174 ms 
    Regex.Replace(str, @"\bfast\b", "12345", RegexOptions.IgnoreCase); // 1076 ms, 3138 ms 
} 
Console.WriteLine((DateTime.UtcNow - start).TotalMilliseconds); 

Составитель регулярное выражение последовательно один из самых медленных из них. Я не вижу такой большой разницы между string.Replace и Regex.Replace, как и вы, но это в одном и том же поле. Поэтому попробуйте его без компиляции регулярного выражения.

Также стоит отметить, что если бы у вас была только одна огромная струна, Regex.Replace быстро вспыхивает, занимая около 7 мс для 13 000 строк гордости и предубеждения на моем ПК.

+0

Я не делаю этого один раз на «BAT» (большой текст $$). Я делаю это несколько раз в одной строке текста. Например, возьмите первое предложение своего ответа и произнесите целое слово на «that» для 1M итераций (очевидно, в моем случае его разные одиночные строки, я просто даю вам пример). Я не могу объединить линии вместе. Их нужно делать по одному. – SledgeHammer

+0

@SledgeHammer Отвечено обновлено. Попробуйте, не компилируя регулярное выражение. Тем не менее, в моем примере Regex примерно на 4x-7x медленнее, чем string.Replace, и вы, вероятно, не можете этого сделать. –

+0

Ничего себе ... это странно! Скомпилированное регулярное выражение должно быть быстрее. Может быть, это просто для более сложных регулярных выражений (или если вы используете регулярные выражения?)? но да, я вижу тот же результат, что и вы ... compiled = 370ms, non-compiled = 205ms. – SledgeHammer

Смежные вопросы