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

Строки php неизменяемы?

Или: Должен ли я оптимизировать свои строковые операции в PHP? Я попытался спросить руководство PHP об этом, но у меня не было никаких намеков ни на что.

4b9b3361

Ответ 1

PHP уже оптимизирует его - переменные присваиваются с использованием copy-on-write, а объекты передаются по ссылке. В PHP 4 это не так, но никто не должен использовать PHP 4 для нового кода.

Ответ 2

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

1. Меньше экземпляров означает меньше времени на строительство.

2. Чем меньше объем памяти, используемой приложением, тем меньше кэша CPU, вероятно, есть.

Для приложений, где скорость является приоритетом №1, существует действительно плотное узкое место между ЦП и ОЗУ. Одной из причин узкого места является латентность ОЗУ.

PHP, Ruby, Python и т.д. связаны с пропуском кэша тем фактом, что даже они хранят хотя бы некоторые (возможно, все) данные во время выполнения интерпретируемых программ в ОЗУ.

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

Здесь run_test.bash измерительного эксперимента:

#!/bin/bash

for i in `seq 1 200`;
do
        /usr/bin/time -p -a -o ./measuring_data.rb  php5 ./string_instantiation_speedtest.php
done

Ниже приведены результаты. /string _instantiation_speedtest.php и результаты измерений:

<?php

// The comments on the
// next 2 lines show arithmetic mean of (user time + sys time) for 200 runs.
$b_instantiate=False; // 0.1624 seconds
$b_instantiate=True;  // 0.1676 seconds
// The time consumed by the reference version is about 97% of the
// time consumed by the instantiation version, but a thing to notice is
// that the loop contains at least 1, probably 2, possibly 4,
// string instantiations at the array_push line.
$ar=array();
$s='This is a string.';
$n=10000;
$s_1=NULL;

for($i=0;$i<$n;$i++) {
    if($b_instantiate) {
        $s_1=''.$s;
    } else {
        $s_1=&$s;
    }
    // The rand is for avoiding optimization at storage.
    array_push($ar,''.rand(0,9).$s_1);
} // for

echo($ar[rand(0,$n)]."\n");

?>

Мой вывод из этого эксперимента и еще один эксперимент, который я сделал с Ruby 1.8, состоит в том, что имеет смысл передавать строковые значения вокруг ссылки.

Один из возможных способов разрешить "pass-strings-by-reference" для всей области приложения - последовательно создавать новый экземпляр строки, когда нужно использовать модифицированную версию строки.

Чтобы увеличить локальность, поэтому скорость, можно уменьшить объем памяти, который потребляет каждый из операндов. Следующий эксперимент демонстрирует случай для конкатенаций строк:

<?php

// The comments on the
// next 2 lines show arithmetic mean of (user time + sys time) for 200 runs.
$b_suboptimal=False; // 0.0611 seconds
$b_suboptimal=True;  // 0.0785 seconds
// The time consumed by the optimal version is about 78% of the
// time consumed by the suboptimal version.
//
// The number of concatenations is the same and the resultant
// string is the same, but what differs is the "average" and maximum
// lengths  of the tokens that are used for assembling the $s_whole.
$n=1000;
$s_token="This is a string with a Linux line break.\n";
$s_whole='';

if($b_suboptimal) {
    for($i=0;$i<$n;$i++) {
        $s_whole=$s_whole.$s_token.$i;
    } // for
} else {
    $i_watershed=(int)round((($n*1.0)/2),0);
    $s_part_1='';
    $s_part_2='';
    for($i=0;$i<$i_watershed;$i++) {
        $s_part_1=$s_part_1.$i.$s_token;
    } // for
    for($i=$i_watershed;$i<$n;$i++) {
        $s_part_2=$s_part_2.$i.$s_token;
    } // for
    $s_whole=$s_part_1.$s_part_2;
} // else

// To circumvent possible optimization one actually "uses" the
// value of the $s_whole.
$file_handle=fopen('./it_might_have_been_a_served_HTML_page.txt','w');
fwrite($file_handle, $s_whole);
fclose($file_handle);

?>

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

Лицензия BSD Реализация PHP и Реализация Ruby алгоритма конкатенации линии водораздела. Тот же алгоритм может быть (был мной) обобщен для ускорения умножения произвольных целых чисел точности.

Ответ 3

Быстрый google, похоже, предположил бы, что они изменяемы, но предпочтительная практика - относиться к ним как к неизменяемым.

Ответ 4

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

Пример:

$a = array_fill(0, 10000, 42);  //Consumes 545744 bytes
$b = $a;                        //   "         48   "
$b[0] = 42;                     //   "     545656   "

$s = str_repeat(' ', 10000);    //   "      10096   "
$t = $s;                        //   "         48   "
$t[0] = '!';                    //   "      10048   "

Ответ 5

Строки PHP неизменяемы.

Попробуйте следующее:

    $a="string";
    echo "<br>$a<br>";
    echo str_replace('str','b',$a);
    echo "<br>$a";

Это echos:

string
bing
string

Если строка была изменчивой, она продолжала бы показывать "bing".