str_replace с помощью strpos?

#php #str-replace #micro-optimization #strpos

#php #str-заменить #микрооптимизация #strpos

Вопрос:

Функция str_replace с проверкой strpos может избежать дополнительной работы?

СПОСОБ 1

 ...
if (strpos($text, $tofind) !== FALSE)
 $text = str_replace($tofind, $newreplace, $text);
...
  

СПОСОБ 2

 ...
$text = str_replace($tofind, $newreplace, $text);
...
  

Вопрос: Эти два метода работают, но… Я хочу знать, является ли strpos-проверка (или другая) хорошим способом или плохим, бесполезным (и антипаттерном оптимизации).

Ответ №1:

Вы можете сохранить некоторые str_replace() вызовы, но вы всегда получаете дополнительные strpos() вызовы и !== false сравнения. Однако я не думаю, что это окажет какое-либо ощутимое влияние, если этот код не будет выполняться около 100000 раз (или тому подобное). Таким образом, пока вам не нужно знать, нужно ли производить замены, вам следует избегать этой «оптимизации», чтобы сделать вещи более простыми и удобочитаемыми.

Ответ №2:

Вы всегда можете рассчитать время самостоятельно:

 $start = 0; $end = 0;

$tofind = 'brown';

// A
$start = microtime(true);
for ($a=0; $a<1000; $a  ) {
    if (strpos('The quick brown fox', $tofind) !== FALSE)
        str_replace($tofind, 'red', 'The quick brown fox');

}
$end = microtime(true);
echo $end - $start . "<br />n";

// B
$start = microtime(true);
for ($b=0; $b<1000; $b  ) {
    str_replace($tofind, 'red', 'The quick brown fox');
}
$end = microtime(true);
echo $end - $start . "<br />n";

/*
various outputs:

0.0021979808807373
0.0013730525970459

0.0020320415496826
0.00130295753479

0.002094030380249
0.0013539791107178

0.0020980834960938
0.0013020038604736

0.0020389556884766
0.0012800693511963

0.0021991729736328
0.0013909339904785

0.0021369457244873
0.0012800693511963

*/
  

Добавление strpos каждый раз происходит медленнее, но ненамного.

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

Комментарии:

1. Не опускайте голос в тишине. Объясните их, чтобы помочь получить лучшие ответы.

2. «каждый раз» — это неправильно, если вы выполняете тест с большим количеством текста и пытаетесь найти что-то, что не завершается, использование strpos может быть быстрее до 30%. Вы, наверное, хотели сказать «обычно».

Ответ №3:

Метод без strpos лучше.

Давайте предположим, что и strpos, и str_replace имеют одинаковое время выполнения в худшем случае, потому что им обоим приходится перебирать весь текст.

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

Ответ №4:

Я только что протестировал 3 способа замены констант в моем конфигурационном файле :

 // No check
function replaceConstantsNoCheck($value)
{
    foreach (array_keys(get_defined_constants()) as $constant)
        $value = str_replace($constant, constant($constant), $value);

    return $value;
}

// Check with strstr
function replaceConstantsStrstr($value)
{
    foreach (array_keys(get_defined_constants()) as $constant)
        if (strstr($value, $constant))
            $value = str_replace($constant, constant($constant), $value);

    return $value;
}

// Check with strpos
function replaceConstantsStrpos($value)
{
    foreach (array_keys(get_defined_constants()) as $constant)
        if (strpos($value, $constant) !== false)
            $value = str_replace($constant, constant($constant), $value);

    return $value;
}
  

Некоторые измерения :

 /*
No check : 0.0078179836273193
Strstr   : 0.0034809112548828
Strpos   : 0.0034389495849609

No check : 0.0067379474639893
Strstr   : 0.0034348964691162
Strpos   : 0.0034480094909668

No check : 0.0064759254455566
Strstr   : 0.0031521320343018
Strpos   : 0.0032868385314941

No check : 0.0068850517272949
Strstr   : 0.003389835357666
Strpos   : 0.0031671524047852

No check : 0.006864070892334
Strstr   : 0.0032939910888672
Strpos   : 0.0032010078430176
*/
  

Ни один метод проверки не использовал минимум вдвое больше времени во всех моих тестах!

Похоже, что между strstr методами и нет существенной разницы strpos .

Ответ №5:

Здесь приводится другой тест: с помощью strpos: http://3v4l.org/pb4hY#v533 без strpos: http://3v4l.org/v35gT