2016-05-06 2 views
4

Так что у меня этот кусок кода в статический метод, называемый CamelizeСтрока camelize низкая производительность

return strtr(ucwords(strtr($id, array('_' => ' ', '.' => '_ ', '\\' => '_ '))), array(' ' => '')); 

Это просто camelizes материал.

У меня около 211 тыс. Записей, итераций по замкнутому циклу, у этих записей есть несколько слов, которые мне нужны для верблюда, самое длинное слово может быть около 10 символов, легкое peasy, но выполнение некоторых тестов xhprof. Я пришел к выводу, что camelize не является хорошим Идея, если вам нужна скорость.

XHProf с camelize: 313,866,303 микросекунд (~ 5мин)

  • 19268795 звонки
  • Incl. Стена Время 228.658.500
  • ICpu: 81,3%

XHProf без camelize: 55,099,811 микросекунд (< 1мин)

Цель этого сценария установить значения свойств класса.

Недвижимость может быть protected $myVar, которая находится на верблюде.

Внутри моего конструктора, я получаю массив подчеркивает свойства (ключи массива), и их значение (значения массива). my_var => foo

Как мы camelized свойства, мы должны преобразовать ключи массива в camelize, так что мы можем сделать что-то вроде $this->$camelizedProperty = $value

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

UPDATE

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

Используемые методы:

  1. strtr(ucwords(strtr($word, array('_' => ' ', '.' => '_ ', '\\' => '_ '))), array(' ' => ''))
  2. lcfirst(str_replace(" ", "", ucwords(strtr($word, "_-", " "))))
  3. str_replace(" ", "", ucwords(strtr($word, "_-", " ")))

Средние результаты над ~ 100 строк на каждой итерации:

  1. 0,0011
  2. 0,0002
  3. 0.0002

Так как указано @RST, используя str_replace составляет 18% быстрее, чем мой первый метод, но по-прежнему медленно (если у нас есть огромный цикл)

На 20М записей, используя xhprof, общие результаты:

  1. 313 секунд (~ 5мин)
  2. 152 секунд (~ 2.5min)
  3. 158 секунд (~ 2.5min)

Можно сказать, что lcfirst не замедляет работу скрипта (я думал, что это может привести к более медленным временам).

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

+0

Что значит «встроенный код»? – RomanPerekhrest

+0

Я имею в виду не вызов статического метода из другого класса, или метод в основном. «camelizing» строку вместо вызова любого метода camelize. –

+0

На что вы его применили? Если это записи базы данных, почему бы не сохранить завершенную форму в кеше в базе данных? – mario

ответ

0

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

раз за 20 миллионов записей следующим образом:

Method 1 time: 301.143823 
Method 2 time: 54.648126 

Правда, здесь код может выглядеть несколько уродливее, но это, видимо, измельчить время вниз. Обратите внимание, что с 5 входными строками просто установите переменную количества выполнения ($ runqty) на 4 миллиона, чтобы получить 20 миллионов таймингов записи для каждого из методов - обязательно закомментируйте операторы эха в циклах в первую очередь.

Пример кода ...

<?php 

$input = array(); 
$input['my_var'] = 'foo'; 
$input['this.that'] = 'blah'; 
$input['try\\me'] = 'strange'; 
$input['some_var_here'] = 'value'; 
$input['final_cut'] = 'fc99'; 

set_time_limit(600); 

$runqty = 1; 

// Method 1 
$m1start = microtime(true); 
for ($runs = 0; $runs < $runqty; $runs++) 
{ 
    foreach ($input as $word => $val) 
    { 
    $out = strtr(ucwords(strtr($word, array('_' => ' ', '.' => '_ ', '\\' => '_ '))), array(' ' => '')); 
    echo "in: $word out: $out<br>\n"; 
    } 
} 
$m1stop = microtime(true); 
$m1time = $m1stop - $m1start; 
echo "Method 1 time: " . sprintf("%0.6f",$m1time); 
echo "<br>\n"; 

// Method 2 
$m2start = microtime(true); 
for ($runs = 0; $runs < $runqty; $runs++) 
{ 
    foreach ($input as $word => $val) 
    { 
    $i=0; 
    $len = strlen($word); 
    $ucnext = true; 
    $out = ''; 

    while ($i < $len) 
    { 
     $char = $word[$i++]; 
     if ($char == '_' || $char == '.' || $char == '\\') 
     { 
     $ucnext = true; 
     if ($char == '.') 
      $char ='_'; 
     else 
      $char = ''; 
     } 
     else 
     { 
     if ($ucnext) 
     { 
      if ($char >= 'a' && $char <= 'z') 
      $char = ucfirst($char); 
      $ucnext = false; 
     } 
     } 

     $out .= $char; 
    } 
    echo "in: $word out: $out<br>\n"; 
    } 
} 
$m2stop = microtime(true); 
$m2time = $m2stop - $m2start; 
echo "Method 2 time: " . sprintf("%0.6f",$m2time); 
echo "<br>\n"; 

Примечание: Если вы не хотите, чтобы первая буква капитализируются, то просто инициализировать ucnext переменную ложным (вместо истины, как показано).

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