Xpoint
   [напомнить пароль]

К сведению: скорости str_replace и strtr

2003-06-26 02:54:40 [обр] Дмитрий Котеров [досье]

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

key => value

где key и value — строки (не обязательно из одного символа). И выяснилась одна поразительная вещь. Если делать это так:

$pairs = array(
  'aa' => '1',
  'bb' => '2',
  # ...
);
$s = strtr($s, $pairs);

то внутри себя PHP применяет такой алгоритм:

for (по одному символу в строке) {
  for (по всем элементам хэша) { 
    if (совпадение начиная с данной позиции) replace
  }
}

Если же применять код:

$k = array('aa', 'bb');
$v = array('1', '2');
$s = str_replace($k, $v, $s);

то алгоритм другой:

for (по всем элементам $k) {
  while (нашли элемент в строке) replace
}

В результате для текста размером 84 К с количеством замен 250, каждая из которых не длиннее 90 символов, strtr работает более чем в 20 (!) раз медленнее, чем str_replace.

Вывод: если замен много, везде, где только можно, откажитесь от strtr(), используйте str_replace.

спустя 8 часов [обр] Евгений Бондарев aka Eugene Bond [досье]
Дмитрий, не стоит так же забывать о том, что strtr во многих случаях более "политкорректен":
$s = "this is a, this is b";
$pairs = array( 
  'a' => 'b', 
  'b' => 'a', 
); 
$s = strtr($s, $pairs); 
echo $s."<br>";

$s = "this is a, this is b";
$k = array('a', 'b'); 
$v = array('b', 'a'); 
$s = str_replace($k, $v, $s); 
echo $s."<br>";
спустя 9 часов [обр] Дмитрий Котеров [досье]
Это да, конечно. Если строки для замены короткие (1-2 символа), то особых потерь нет. Но если они длинные — вот тогда тормозит ужасно.
спустя 2 месяца 7 дней [обр] Dag [досье]

> Вывод: если замен много, везде, где только можно, откажитесь от strtr(), используйте str_replace.

And preg_replace is much faster then str_replace:) (2 times app. - long docs.)

спустя 3 месяца 3 дня [обр] Алексей Волков, он же „Росомаха из Флориды“ [досье]
And preg_replace is much faster then str_replace
Это как же может быть такое, интересно. Очень интересно. С трудом верится, что запуск и компиляция регулярного выражения вместе с поиском стоят дешевле, нежели str_replace.
спустя 2 дня 3 часа [обр] Dag [досье]

:: And preg_replace is much faster then str_replace
: Это как же может быть такое, интересно. Очень интересно.***

Рад что Вам интересно Алексей. И, конечно, абсолютно согласен с Вами что речь идет не о правильном использованию preg_replace (обработка чистой строки). Тем не менее: в следующем коду разница (примерно) такая какую я обозначил:

$cyrillic=array(a,b,v...);
$tliter=array(x,y,z...);
function &cyr2latru($str) {return str_replace($cyrillic,$tliter,$str);}
$data=$someLargeText;
$transliterated=cyr2latru($data);
print $transliterated;

спустя 2 дня 17 часов [обр] Алексей Волков, он же „Росомаха из Флориды“ [досье]
Пример, пожалуйста, обеих функций и вывод бенчмарка по циклу в тысячу проходов, можно? С трудом верится, что при замене одного символа в строке с массивами для поиска и замены preg_replace оказывается быстрее.
спустя 1 день 10 часов [обр] Dag [досье]

Алексей Волков
Это как же может быть такое, интересно. Очень интересно. С трудом верится ...

code

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

Да все можно наверно только кто это должен сделать: Вы или я? Я думаю Вы. Есть утверждение в котором Вы очень сомневаетесь. Есть и код. Так в период: докажите что я не прав. Зачем мне кому либо что либо доказывать...

Но... персонаж же Вы положительный:)) (в интернете все мы просто персонажи) так что:..

Дата: 2003-07-04
Размер файла: 105 кб
PHP ver - ?

_Cyr to Lat_ (IBM CP 1251)
нн.   --   str_replace   --   preg_replace
---
1.   --   0.804847002029   -- 0.436069011688
2.   --   0.876431941986   -- 0.453631997108
3.   --   0.850198030472   -- 0.431483983994
4.   --   0.817659974098   -- 0.452099084854
5.   --   0.853718996048   -- 0.426046967506

_Lat to Cyr_ (IBM CP 1251)
нн.   --   str_replace   --   preg_replace
---
1.   --   0.699434995651   -- 0.396942973137
2.   --   0.627966046333   -- 0.446587085724
3.   --   0.656357049942   -- 0.413340091705
4.   --   0.764477968216   -- 0.462484002113
5.   --   0.723194003105   -- 0.578529953957

Скромное число повторов конечно но достаточно что бы задуматься (тест не я делал). Язык не русский и нет перевода 1char <-> 2 chars. Сам не стану для строк использовать прег... надежность прежде всего. Так что, смотрите сами:

http://orwell.ru/test/php/_replace

[time at the page-bottom]

Поделитесь выводами.

спустя 14 дней [обр] Алексей Волков, он же „Росомаха из Флориды“ [досье]

Dag[досье], обычно доказательства приводит тот, кто выдвигает какой-то аргумент. Кто это был, как вы думаете?

Смысл как раз в том, чтобы провести тест, в котором будет отчётливо видно — одно из решений более эффективно, чем другое. Не на сотых долях секунд, а на целых или десятках секунд. На вашей тестовой странице есть только перекодировка кириллицы в латиницу, и на тестовых образцах preg_replace там опережает str_replace в среднем на две пятых.

Комментарий к коду: таймер лучше поставить вокруг вызова перекодирующей функции, чтобы все остальные операции в расчёт не брались.

спустя 10 часов [обр] Dag [досье]
обычно доказательства приводит тот, кто выдвигает какой-то аргумент.

Не согласен (но вижу что Вас не переубедишь). Если бы каждое утверждение на каждом форуме провожалось примером... Мнений типа "С трудом верится" гораздо меньше. Я лично часто проверяю высказанное и если есть сомнение сам делаю пример (заметили наверно что не из ленивых).

На вашей тестовой странице есть только перекодировка кириллицы в латиницу, и на тестовых образцах preg_replace там опережает str_replace в среднем на две пятых.

А я другое и не говорил. 2/5 очень много.

таймер лучше поставить вокруг вызова перекодирующей функции

Виноват (и то еще как!..).

// -------------------------------------------------------- methods
switch ($method) {
case 'Str_Replace':
   $tStart=microtime();
   $modDIR = $_SERVER["DOCUMENT_ROOT"] . "/moduls/";
   $output=cyr2latStr($string);
   break;
case 'Preg_Replace':
   $tStart=microtime();
   $modDIR = $_SERVER["DOCUMENT_ROOT"] . "/moduls/";
   $output=cyr2latPrg($string);}
// -------------------------------------------------------- time end
$tEnd=microtime();
$aA=explode(' ',$tStart.' '.$tEnd);
$tSeconds=sprintf('%01.8f seconds',($aA[2]+$aA[3])-($aA[0]+$aA[1]));

Результат иной (мне кажется).

спустя 10 минут [обр] Dag [досье]
$modDIR = $_SERVER["DOCUMENT_ROOT"] . "/moduls/";

Чушь какая-то... to be deleted
А заметили на сколько отличается тип обращения серверу у каждого браузера?

Text file:
http://orwell.ru/test/php/_script

спустя 4 часа 56 минут [обр] Дмитрий Котеров [досье]
А еще можно исходники PHP посмотреть и узнать, почему одна функция медленнее (или быстрее) другой и в каких примерно случаях.
спустя 3 часа 55 минут [обр] Dag [досье]
спустя 8 часов [обр] Алексей Волков, он же „Росомаха из Флориды“ [досье]
Слова Дмитрия „Исходники PHP“ в данном случае означают не исходный код вашего скрипта, Dag O, а исходный код самого PHP.
спустя 3 минуты [обр] Алексей Волков, он же „Росомаха из Флориды“ [досье]
Да, теперь лучше видно, и ещё меньше понятно, почему str_replace работает настолько (почти наполовину) медленнее.
спустя 44 минуты [обр] Dag [досье]
Я понял... Это, на самом деле и было первым что я подумал... по идеи, прег должен быт гораздо круче... сложные задаче у него... и кода наверно по больше (и проверок:)). А кто ни будь слышал про фразу типа "Если хочешь что бы прога быстро работала, пиши большой код."? Когда-то нам так говорили...
спустя 1 час 10 минут [обр] Алексей Волков, он же „Росомаха из Флориды“ [досье]
Сложно сказать без просмотра движка регулярных выражений, но есть мнение, что там очень сильно оптимизирована обработка именно больших массивов данных — чем больше, тем лучше, поэтому на коротких строках и на задачах без многоцикловых проходов (с несколькими массивами и т.п.) str_replace, использующая приведённый выше Дмитрием метод, будет оптимальнее просто из-за того, что используется „свой“ код, а не внешний модуль.
Powered by POEM™ Engine Copyright © 2002-2005