Что более эффективно, строковые функции PHP или регулярное выражение в PHP?


Я пишу PHP-код для анализа строки. Это должно быть как можно быстрее, так можно ли использовать регулярные выражения? У меня есть предчувствие, что строковые функции PHP дороже, но это всего лишь предположение. В чем же правда?

Вот конкретно, что мне нужно сделать со строкой:

Возьмите первую половину (на основе третьего местоположения подстроки "000000") и сравните ее хэш со следующими 20 байтами, отбросив все, что осталось.

Проанализируйте 9-й байт через следующий "000000" как один фрагмент данных. Затем возьмите следующие 19 байт после этого и разделите их на 8 (бросьте 1) и 8. Затем я делаю еще кое-что, что преобразует эти две 8-байтовые строки в даты.

Так что это то, что мне нужно сделать.

Author: Parrots, 2009-03-11

9 answers

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

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


Отредактируйте с новой информацией в OP:

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

Захватите первую половину (на основе третьего расположения подстроки "000000") и сравните его хэш со следующими 20 байтами, отбросив все, что осталось.

Использовать: strpos() и substr()
Или : /$(.*?0{6}.*?0{6}.*?)0{6}/

Затем возьмите следующие 19 байтов после этого и разделите их на 8 (бросьте 1) и 8.

Использовать: substr() - ( Я предполагаю, что вы имеете в виду 17 байт здесь -- 8 + 1 + 8)

$part1 = substr($myStr, $currPos, 8);
$part2 = substr($myStr, $currPos + 9, 8);
 16
Author: nickf, 2009-03-11 23:11:45

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

РЕДАКТИРОВАТЬ: Для этой конкретной проблемы, которую вы опубликовали, я бы предпочел строковые операции, но только потому, что я не знал бы, как это сделать в регулярном выражении. Это кажется довольно простым, за исключением хэша, поэтому я думаю, что функции регулярных выражений/строк не будут иметь большого значения.

 6
Author: schnaader, 2009-03-11 14:27:07

Я считаю, что существует порог, начиная с которого регулярное выражение выполняется быстрее, чем набор вызовов строковых функций PHP. В любом случае, многое зависит от того, что вы делаете. Вы должны найти баланс.

Теперь, когда вы отредактировали свой вопрос. Я бы использовал строковые функции для того, чего вы пытаетесь достичь. strpos() и substr() - это то, что приходит на ум с первого взгляда.

 6
Author: Ionuț G. Stan, 2009-03-11 14:28:30

В общем случае строковые функции работают быстрее, а функции регулярных выражений более гибкие.

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

 4
Author: Hugh Bothwell, 2009-03-12 00:24:04

Если то, что вы делаете, вообще разумно делать с помощью строковых функций, вы должны их использовать. Например, если вы определяете, встречается ли постоянная строка 'abc' в $value, вы определенно хотите проверить strpos($value, 'abc') !== false, а не preg_match('/abc/', $value). Однако, если вы обнаружите, что делаете много перестановок и преобразований строк, чтобы выполнить то, что вы сделали бы с регулярным выражением, вы почти наверняка уничтожите как производительность, так и ремонтопригодность.

Когда речь идет о скорости, хотя, когда дело доходит до этого, не думай об этом, засекай время. Команда time - ваш друг.

 4
Author: chaos, 2012-03-13 21:41:09

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

Стрпо():

$ time php -r '$i = 0; while($i++ < 1000000) strpos("abc", "a");'

real    0m0.380s
user    0m0.368s
sys    0m0.008s

Preg_матч():

$ time php -r '$i = 0; while($i++ < 1000000) preg_match("/abc/", "a");'

real    0m0.441s
user    0m0.432s
sys    0m0.004s
 2
Author: milkovsky, 2017-04-20 11:55:47

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

 1
Author: Joonas Pulakka, 2009-03-11 14:16:29

Зависит от ваших потребностей. Большинство операций с регулярными выражениями выполняются быстрее, чем можно было бы подумать, и могут даже превосходить встроенные строковые функции в некоторых тривиальных операциях. Обратите внимание, что я имею в виду библиотеку preg, а не встроенную библиотеку регулярных выражений, которая довольно медленная.

 0
Author: soulmerge, 2009-03-11 14:22:39

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

Спецификация: Мне нужно найти простую строку в массиве строк. Для проверки у меня есть $testArray, который представляет собой массив из ~11 тысяч словосочетаний, собранных из статьи о Толкине (например, строки "история властелина колец", "кристофер Толкиен"). Как Я хочу найти только фразы, содержащие точное слово, которое я не могу использовать как функцию strpos(), например. при поиске "звонка" он также найдет фразы со словом "мелодия звонка".

Код с использованием функций php:

$results = array();
$searchWord = 'rings';
foreach ($testArray as $phrase){
  $phraseArr = explode(' ', $phrase);
  if(in_array($searchWord, $phraseArr)){
    $results[] = $phrase;
  }
}

Код с использованием функции регулярного выражения:

$results = array();
$pattern= "/( |^)rings( |$)/";
$results = preg_grep($pattern, $testArray);

Я обнаружил, что в этом случае функция регулярного выражения была примерно в 10 раз быстрее

Время выполнения для 100 поисков было (с использованием различных слов)

  • от 0,3436 до 0,3468 секунды для функций php
  • из от 0,0332 до 0,0406 секунды для регулярного выражения

Такой поиск может быть тривиальным, но для более сложных задач, я полагаю, было бы чрезвычайно сложно/невозможно реализовать его без регулярного выражения только для собственных функций php.

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

Изменить:

Я просто поймите, что эта тема посвящена "строковым функциям PHP ", и мой тестовый код использует функции explode() и in_array(). Поэтому я попробовал другой подход. Поскольку мой разделитель - это метод поиска пространства, приведенный ниже, также работает и использует функцию strpos().

Код с использованием функции strpos():

$results = array();
$searchWord = 'rings';
foreach ($testArray as $phrase){
  if(strpos(' ' . $phrase . ' ', ' ' . $searchWord . ' ')!==FALSE){
    $results[] = $phrase;
  }
} 

Но все равно результаты были намного хуже, чем в случае регулярного выражения.

Итак, краткое описание производительности таково:

  • от 0,3436 до 0,3468 секунды для функций массива php
  • с 0.2001 по 0.2273 второй для функции strpos()
  • от 0,0332 до 0,0406 секунды для регулярного выражения

Тем не менее регулярное выражение является большим победителем.

 0
Author: Jacek Rosłan, 2018-09-14 10:40:41