Подтвердить что ты не робот

Каков наилучший способ добавить две строки вместе?

Я читал где-нибудь (я думал о 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);

Это даже имеет значение?

4b9b3361

Ответ 1

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

Ответ 2

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

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

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

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

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

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

Ответ 3

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

Одиночный concat:

$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

Как вывод, становится очевидным, что единственный concat через точку (.) char является самым быстрым. И для случаев, когда у вас много конкатений, наилучшим образом используемым методом является использование прямой вставки строк с помощью синтаксиса "injection: $inject".

Ответ 4

Если его действительно большой объем текста действительно не имеет значения.

Ответ 5

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

$output = "$str1$str2";

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

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

Ответ 6

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

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

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

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

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

Если вы идентифицируете его как проблему, попробуйте googling для класса построителя php string (некоторые из них будут найдены) или напишите свой собственный.

Ответ 7

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

    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(), если вам нужно что-то кричать быстро, но нет большой разницы между всеми обычными методами.

Ответ 8

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

Конкатенация, возьмите 2 строки, выделите размер памяти length1 + length2 и скопируйте каждый в новую память. самый быстрый для 2 строк. Однако при объединении 10 строк требуется 9 операций concat. Используемая память - это 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 похож на использование атомной бомбы памяти, чтобы присоединиться к двум небольшим строкам, но очень эффективен, когда есть много соединений, циклов, условий или добавок слишком динамичны для чистого sprintf. concat является наиболее эффективным, чтобы присоединиться к нескольким фиксированным строкам, sprintf, который работает лучше для создания строки из фиксированных значений за один раз.

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

Ответ 9

Совет, который вы прочитали, может быть связан с функцией echo, для которой он быстрее использует запятые, например:

echo $str1, $str2;

Другой подход заключается в создании строки в переменной (например, с использованием оператора.), а затем эхо всей строки в конце.

Вы можете проверить это самостоятельно, используя функцию microtime (вам нужно сделать цикл, который повторяется, например, 1000 или 100 000 раз, чтобы сделать цифры значительными). Но из четырех вы отправили, первый, скорее всего, будет самым быстрым. Это также наиболее читаемо - другие не имеют никакого смысла программно.

Ответ 10

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

$tmp=srray();
for(;;) $tmp[]='some string';
$str=implode('',$tmp);

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

Ответ 11

Я не 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 быстро добавляет новые элементы.

Ответ 12

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

ob_start();

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

$finalstr = ob_get_clean();

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