或者:我应该在PHP中优化我的字符串操作吗?我尝试向PHP手册询问,但没有得到任何有关此事的提示。
注:以上内容已翻译并保留了HTML标签。
PHP已经进行了优化-变量是使用写时复制copy-on-write分配的,对象是通过引用传递的。在PHP 4中没有这样做,但无论如何,没有人应该为新代码使用PHP 4。
function f($obj) { $obj = 'foo'; } $obj = new stdClass; f($obj); var_dump($obj);
。如果 $ obj
是按引用传递的,它将输出 'foo'
而不是 'stdClass'
;) - NikiC在许多编程语言中,最重要的速度优化技术之一是实例重用。在这种情况下,速度增加至少有两个因素:
1. 实例化较少意味着构建所需的时间更短。
2. 应用程序使用的内存越少,可能发生的CPU缓存未命中就越少。
对于速度是第一优先级的应用程序来说,CPU和RAM之间存在一个非常紧密的瓶颈。瓶颈的原因之一是RAM的延迟。
PHP、Ruby、Python等语言与缓存未命中相关,因为它们至少将解释程序的某些(可能全部)运行时数据存储在RAM中。
字符串实例化是一种经常进行的操作,数量相对较大,并且可能对速度产生明显影响。
这里是一个测量实验的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");
?>
<?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);
?>
数组和字符串具有写时复制的行为。它们是可变的,但当你最初将它们赋值给一个变量时,该变量将包含完全相同的字符串或数组实例。只有在修改数组或字符串时才会进行复制。
示例:
$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 "
PHP 7.4 使用可变字符串:
<?php
$str = "Hello\n";
echo $str;
$str[2] = 'y';
echo $str;
输出:
Hello
Heylo
测试:PHP沙盒
PHP字符串是不可变的。
试试这个:
$a="string";
echo "<br>$a<br>";
echo str_replace('str','b',$a);
echo "<br>$a";
它回显:
string
bing
string
$a = 'hello '; echo $a; $a[3] = 'd'; echo $a;
- Anon343224user