Каков наилучший способ сложить две строки вместе? - PullRequest
21 голосов
/ 29 марта 2009

Я где-то читал (я думал о codinghorror), что это плохая практика - добавлять строки вместе, как если бы они были числами, поскольку, как и числа, строки нельзя изменить. Таким образом, сложение их вместе создает новую строку. Итак, мне было интересно, как лучше всего сложить две строки вместе, ориентируясь на производительность?

Какой из этих четырех лучше или есть другой способ, который лучше?

//Note that normally at least one of these two strings is variable
$str1 = 'Hello ';
$str2 = 'World!'; 
$output1 = $str1.$str2; //This is said to be bad

$str1 = 'Hello ';
$output2 = $str1.'World!'; //Also bad

$str1 = 'Hello';
$str2 = 'World!';
$output3 = sprintf('%s %s', $str1, $str2); //Good?
//This last one is probaply more common as:
//$output = sprintf('%s %s', 'Hello', 'World!');

$str1 = 'Hello ';
$str2 = '{a}World!';
$output4 = str_replace('{a}', $str1, $str2);

Это вообще имеет значение?

Ответы [ 12 ]

37 голосов
/ 29 марта 2009

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

$str1 = "Hello";
$str1 .= " World";

Не помещайте их в двойные кавычки, такие как $result = "$str1$str2";, так как это приведет к дополнительным накладным расходам при разборе символов внутри строки.

Если вы собираетесь использовать это только для вывода с помощью echo, используйте функцию echo, которая позволяет передавать ему несколько параметров, поскольку это не приведет к генерации новой строки:

$str1 = "Hello";
$str2 = " World";
echo $str1, $str2;

Для получения дополнительной информации о том, как PHP обрабатывает интерполированные строки и конкатенацию строк посмотрите блог Сары Гоулман .

13 голосов
/ 29 марта 2009

Вы всегда будете создавать новую строку, объединяя две или более строк вместе. Это не обязательно «плохо», но может иметь последствия для производительности в определенных сценариях (например, тысячи / миллионы конкатенаций в узком цикле). Я не парень PHP, поэтому я не могу дать вам никаких советов по семантике различных способов объединения строк, но для конкатенации одной строки (или только нескольких) просто сделайте ее читабельной. Вы не увидите снижения производительности из-за небольшого количества из них.

11 голосов
/ 01 января 2013

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

Одинарный конкат:

$iterations = 1000000;
$table = 'FOO';
$time = microtime(true);
for ($i = 0; $i < $iterations; $i++) {
        $sql = sprintf('DELETE FROM `%s` WHERE `ID` = ?', $table);
}
echo 'single sprintf,',(microtime(true) - $time)."\n";

$time = microtime(true);
for ($i = 0; $i < $iterations; $i++) {
        $sql = 'DELETE FROM `' . $table . '` WHERE `ID` = ?';
}
echo 'single concat,',(microtime(true) - $time)."\n";

$time = microtime(true);
for ($i = 0; $i < $iterations; $i++) {
        $sql = "DELETE FROM `$table` WHERE `ID` = ?";
}
echo 'single "$str",',(microtime(true) - $time)."\n";

Я получаю эти результаты:

single sprintf,0.66322994232178
single concat,0.18625092506409 <-- winner
single "$str",0.19963216781616

Множество конкатов (10):

$iterations = 1000000;
$table = 'FOO';
$time = microtime(true);
for ($i = 0; $i < $iterations; $i++) {
        $sql = sprintf('DELETE FROM `%s`,`%s`,`%s`,`%s`,`%s`,`%s`,`%s`,`%s`,`%s`,`%s` WHERE `ID` = ?', $table, $table, $table, $table, $table, $table, $table, $table, $table, $table);
}
echo 'many sprintf,',(microtime(true) - $time)."\n";

$time = microtime(true);
for ($i = 0; $i < $iterations; $i++) {
        $sql = 'DELETE FROM `' . $table . '`,`' . $table . '`,`' . $table . '`,`' . $table . '`,`' . $table . '`,`' . $table . '`,`' . $table . '`,`' . $table . '`,`' . $table . '`,`' . $table . '` WHERE `ID` = ?';
}
echo 'many concat,',(microtime(true) - $time)."\n";

$time = microtime(true);
for ($i = 0; $i < $iterations; $i++) {
        $sql = "DELETE FROM `$table`,`$table`,`$table`,`$table`,`$table`,`$table`,`$table`,`$table`,`$table`,`$table` WHERE `ID` = ?";
}
echo 'many "$str",',(microtime(true) - $time)."\n";

Результаты:

many sprintf,2.0778489112854
many concats,1.535336971283
many "$str",1.0247709751129 <-- winner

В заключение становится очевидным, что один конкат через точку (.) Char является самым быстрым. А для случаев, когда у вас много конкатов, самый эффективный метод - это прямое внедрение строк через синтаксис "injection: $inject".

5 голосов
/ 29 марта 2009

Если текст не очень большой, это не имеет значения.

3 голосов
/ 29 марта 2009

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

Пример 1 и 2 похожи, я не думаю, что должно быть много различий, это будет пост всех. № 1 может быть немного быстрее.

Пример 3 будет работать медленнее, поскольку необходимо проанализировать формат sprintf ('% s% s').

Пример 4 выполняет замену, которая включает в себя поиск по строке - дополнительная операция занимает больше времени.

Но, во-первых, конкатенация строк - это проблема производительности? Это очень маловероятно, вы должны профилировать код, чтобы измерить, сколько времени требуется для его запуска. Затем замените метод конкатенации другим и снова.

Если вы считаете, что это проблема, попробуйте поискать в Google php string builder class (есть такие, которые можно найти) или напишите свой собственный.

3 голосов
/ 29 марта 2009

Как говорили другие, $str1 . $str2 в большинстве случаев вполне нормально, за исключением (больших) циклов.
Обратите внимание, что вы пропускаете некоторые решения:

$output = "$str1$str2";

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

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

2 голосов
/ 11 июня 2014

Нашел этот пост в Google и подумал, что проведу несколько тестов, так как мне было любопытно, каков будет результат. (Проведено сравнение более 10000 итераций с использованием эталона, который вычитает собственные издержки.)

    Which                        2 strings   10 strings   50 strings
    ----------------------------------------------------------------
    $a[] then implode()         2728.20 ps      6.02 μs     22.73 μs
    $a . $a . $a                 496.44 ps      1.48 μs      7.00 μs
    $b .= $a                     421.40 ps ★    1.26 μs      5.56 μs
    ob_start() and echo $a      2278.16 ps      3.08 μs      8.07 μs
    "$a$a$a"                     482.87 ps      1.21 μs ★    4.94 μs ★
    sprintf()                   1543.26 ps      3.21 μs     12.08 μs

Так что в этом не так много. Возможно, стоит избегать sprintf() и implode(), если вам нужно что-то, чтобы кричать быстро, но между всеми обычными методами нет большой разницы.

1 голос
/ 01 декабря 2011

Существует 3 типа операций объединения строк.

Объединить, взять 2 строки, выделить размер памяти length1 + length2 и скопировать каждый в новую память. Самый быстрый для 2 строк. Однако для конкатенации 10 строк требуется 9 конкатных операций. Используемая память - 1-я строка 10 раз, 2-я строка 10 раз, 3-я строка 9 раз, 4-я строка 8 раз и т. Д. Выполняет операции X + 1 + (X-1) * 2, используя больше памяти каждый цикл.

sprintf (array_merge, join и т. Д.), Взять все строки вместе, суммировать их длину, выделить новую строку суммы размеров, а затем скопировать каждую строку на свое место. используемая память - 2 * длина всех начальных строк, а операции - 2 * X (каждая длина, каждая копия)

ob (выходной буфер) выделяет общий блок 4k и копирует в него каждую строку. память 4k + каждая начальная строка, операции = 2 + X. (начало, конец, каждая копия)

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

Я не знаю, какая рутина php использует в этой ситуации: $ x $ y $ z, может быть просто уменьшено до встроенного $ x. "" $ y. "" $ Г

0 голосов
/ 20 октября 2011

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

ob_start();

echo $str1;
echo $str2;
.
.
.
echo $str_n;

$finalstr = ob_get_clean();

Этот метод обеспечивает единообразное хранение всех строк и отсутствие затрат на обработку или объединение. С последней строкой кода вы также получаете весь буфер. Вы можете безопасно запускать циклы вместо независимого эха.

0 голосов
/ 27 декабря 2009

Я не гуру PHP, однако, во многих других языках (например, Python), самый быстрый способ создать длинную строку из множества небольших строк - это добавить строки, которые вы хотите объединить, в список, а затем присоединиться к ним, используя встроенный метод соединения. Например:

$result = array();
array_push("Hello,");
array_push("my");
array_push("name");
array_push("is");
array_push("John");
array_push("Doe.");
$my_string = join(" ", $result);

Если вы строите огромную строку в узком цикле, самый быстрый способ сделать это - добавить массив, а затем присоединить массив в конце.

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

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