Взрыв массива в параметре цикла foreach - PullRequest
10 голосов
/ 02 мая 2011
foreach(explode(',' $foo) as $bar) { ... }

против

$test = explode(',' $foo);
foreach($test as $bar) { ... }

В первом примере это explode строка $foo для каждой итерации или PHP хранит ее в памяти, взорванной в собственной временной переменной? С точки зрения эффективности, имеет ли смысл создавать дополнительную переменную $test или они в значительной степени равны?

Ответы [ 4 ]

22 голосов
/ 03 мая 2011

Я мог бы сделать обоснованное предположение, но давайте попробуем !

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

  1. взорваться иприсваивать перед входом в цикл
  2. взрываться внутри цикла, нет присваивания
  3. строка токенизации

Мои гипотезы:

  1. вероятно потребляют большепамять из-за присваивания
  2. , вероятно, идентична # 1 или # 3, не уверен, что
  3. , вероятно, и быстрее, и намного меньше занимаемой памяти

Подход

Вот мой тестовый скрипт:

<?php

ini_set('memory_limit', '1024M');

$listStr = 'text';
$listStr .= str_repeat(',text', 9999999);

$timeStart = microtime(true);

/*****
 * {INSERT LOOP HERE}
 */

$timeEnd = microtime(true);
$timeElapsed = $timeEnd - $timeStart;

printf("Memory used: %s kB\n", memory_get_peak_usage()/1024);
printf("Total time: %s s\n", $timeElapsed);

И вот три версии:

1)

// explode separately 
$arr = explode(',', $listStr);
foreach ($arr as $val) {}

2)

// explode inline-ly 
foreach (explode(',', $listStr) as $val) {}

3)

// tokenize
$tok = strtok($listStr, ',');
while ($tok = strtok(',')) {}

Результаты

explode() benchmark results

Выводы

Похоже, некоторые предположения были опровергнуты.Разве ты не любишь науку?: -)

  • В целом, любой из этих методов достаточно быстр для создания списка «разумных размеров» (несколько сотен или нескольких тысяч).
  • Если выитерация чего-то огромная , разница во времени относительно мала, но использование памяти может отличаться на порядок!
  • Когда вы explode() встраиваете без предварительного назначения, это немного медленнеепо какой-то причине.
  • Удивительно, но токенизация немного на медленнее , чем явная итерация объявленного массива.Работая в таком небольшом масштабе, я полагаю, что это связано с накладными расходами стека вызовов при вызове функции для strtok() каждой итерации.Подробнее об этом ниже.

С точки зрения количества вызовов функций, explode() действительно возглавляет токенизацию. O (1) против O (n)

Я добавил бонус на график, где я запускаю метод 1) с помощью вызова функции в цикле.Я использовал strlen($val), думая, что это будет относительно похожее время выполнения.Это подлежит обсуждению, но я только пытался сделать общее замечание.(Я только набрал strlen($val) и проигнорировал его вывод. Я не присвоил его чему-либо, так как назначение было бы дополнительными временными затратами.)

// explode separately 
$arr = explode(',', $listStr);
foreach ($arr as $val) {strlen($val);}

Как вы можетекак видно из таблицы результатов, он становится самым медленным методом из трех.

Заключительная мысль

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

6 голосов
/ 02 мая 2011

В первом случае PHP разбирает его один раз и сохраняет в памяти.

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

3 голосов
/ 03 мая 2011

С точки зрения памяти это не будет иметь значения, потому что PHP использует копию при записи концепции .

Кроме того, я лично выбрал бы первый вариант - это строка меньше, но не менее читабельная (imho!).

1 голос
/ 02 мая 2011

Эффективность в каком смысле? Управление памятью или процессор? Процессор не будет иметь значения, для памяти - вы всегда можете сделать $foo = explode(',', $foo)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...