Хотя компиляция регулярного выражения занимает какое-то время, я бы не отказался от использования pcre так легко. Если вы не найдете функцию сравнения, которая принимает несколько игл, вам нужен цикл для игл, и выполнение цикла + вызов функции сравнения для каждой отдельной иглы также требует времени.
Возьмем тестовый скрипт, который извлекает все имена функций из php.net и ищет определенные окончания. Это был только adhoc-скрипт, но я полагаю, что какая бы ни была функция strcmp-ish function +, которую вы используете, будет медленнее, чем простой шаблон pcre (в данном случае).
count($hs)=5549
pcre: 4.377925157547 s
substr_compare: 7.951938867569 s
identical results: bool(true)
Это был результат поиска девяти различных моделей. Если бы было только два («yadda», «ge»), оба метода принимали одно и то же время.
Не стесняйтесь критиковать тестовый скрипт (не всегда ошибки в синтетических тестах, которые очевидны для всех, но сам ;-)?)
<?php
/* get the test data
All the function names from php.net
*/
$doc = new DOMDocument;
$doc->loadhtmlfile('http://docs.php.net/quickref.php');
$xpath = new DOMXPath($doc);
$hs = array();
foreach($xpath->query('//a') as $a) {
$hs[] = $a->textContent;
}
echo 'count($hs)=', count($hs), "\n";
// should find:
// ge, e.g. imagick_adaptiveblurimage
// ing, e.g. m_setblocking
// name, e.g. basename
// ions, e.g. assert_options
$ns = array('yadda', 'ge', 'foo', 'ing', 'bar', 'name', 'abcd', 'ions', 'baz');
sleep(1);
/* test 1: pcre */
$start = microtime(true);
for($run=0; $run<100; $run++) {
$matchesA = array();
$pattern = '/(?:' . join('|', $ns) . ')$/';
foreach($hs as $haystack) {
if (preg_match($pattern, $haystack, $m)) {
@$matchesA[$m[0]]+= 1;
}
}
}
echo "pcre: ", microtime(true)-$start, " s\n";
flush();
sleep(1);
/* test 2: loop + substr_compare */
$start = microtime(true);
for($run=0; $run<100; $run++) {
$matchesB = array();
foreach($hs as $haystack) {
$hlen = strlen($haystack);
foreach($ns as $needle) {
$nlen = strlen($needle);
if ($hlen >= $nlen && 0===substr_compare($haystack, $needle, -$nlen)) {
@$matchesB[$needle]+= 1;
}
}
}
}
echo "substr_compare: ", microtime(true)-$start, " s\n";
echo 'identical results: '; var_dump($matchesA===$matchesB);
'Поиск массива: er, wr, de' - они всегда имеют одинаковую длину или же это может быть что-то вроде' er, a, xyz'? Насколько «важна» эта оптимизация? Это действительно узкое место в вашем приложении? – VolkerK
Элементы в массиве поиска различаются по размеру. Я ищу пару сотен. Результат кэшируется, но я все же хочу свести к минимуму работу. – 2009-09-25 20:12:58