我正在使用PHP编写一个解析器,必须能够处理大型内存字符串,因此这是一个相当重要的问题。(也就是说,请不要“过早优化”抨击我,请)
substr
函数如何工作?它是否会在内存中创建第二个字符串数据副本,还是只是引用原始字符串?我应该担心在循环中调用$str = substr($str, 1);
这样的函数吗?
我正在使用PHP编写一个解析器,必须能够处理大型内存字符串,因此这是一个相当重要的问题。(也就是说,请不要“过早优化”抨击我,请)
substr
函数如何工作?它是否会在内存中创建第二个字符串数据副本,还是只是引用原始字符串?我应该担心在循环中调用$str = substr($str, 1);
这样的函数吗?
strpos()
的第三个参数)。通常我会建议编写一个对象来封装这个功能,但如果你期望经常使用它,那可能会造成性能瓶颈。以下是一个没有面向对象的示例: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 :-(
是的,在循环中进行任何字符串操作时,应该小心,因为每次迭代都会生成新的字符串副本。