我正在用 PHP 编写一个解析器,它必须能够处理大型内存中的字符串,所以这是一个重要的问题。(即,请不要“过早优化”我,拜托)
该功能如何substr
工作?它是在内存中复制字符串数据,还是引用原始数据?例如,我是否应该担心$str = substr($str, 1);
在循环中调用?
我正在用 PHP 编写一个解析器,它必须能够处理大型内存中的字符串,所以这是一个重要的问题。(即,请不要“过早优化”我,拜托)
该功能如何substr
工作?它是在内存中复制字符串数据,还是引用原始数据?例如,我是否应该担心$str = substr($str, 1);
在循环中调用?
如果你真的在研究效率,你需要在你的字符串中保留一个指针——我的意思是索引。许多字符串函数接受一个偏移量来开始操作(如strpos()
的第三个参数)。通常我会建议编写一个对象来包装这个功能,但如果你期望大量使用它,那可能会导致性能瓶颈。这是我的意思的一个例子(没有OO):
while ($whatever) {
$pos = strpos($string, $myToken, $startIndex);
# do something using $pos
$startIndex = $pos;
}
如果需要,您可以编写自己的包装类来执行这些字符串操作,看看它是否对速度有影响:
class _String {
private $string;
private $startIndex;
private $length;
public function __construct($string) {
$this->string = $string;
$this->startIndex = 0;
$this->length = strlen($string);
}
public function substr($from, $length = NULL) {
$this->startIndex = $from;
if ($length !== NULL) {
$this->endIndex = $from + $length;
}
}
# other functions you might use
# ...
}
为了进一步 Chad 的评论,您的代码将要求两个字符串(完整的字符串和完整的一个减第一个字符)同时在内存中(尽管不是由于 Chad 所说的分配)。看:
$string = str_repeat('x', 1048576);
printf("MEM: %d\nPEAK: %d\n", memory_get_usage(), memory_get_peak_usage());
substr($string, 1);
printf("MEM: %d\nPEAK: %d :-(\n", memory_get_usage(), memory_get_peak_usage());
$string = substr($string, 1);
printf("MEM: %d\nPEAK: %d :-(\n", memory_get_usage(), memory_get_peak_usage());
输出类似(内存值以字节为单位):
MEM: 1093256
PEAK: 1093488
MEM: 1093280
PEAK: 2142116 :-(
MEM: 1093276
PEAK: 2142116 :-(
是的,您应该小心在循环内进行任何字符串操作,因为每次迭代都会生成字符串的新副本。