8

我正在用 PHP 编写一个解析器,它必须能够处理大型内存中的字符串,所以这是一个重要的问题。(即,请不要“过早优化”我,拜托)

该功能如何substr工作?它是在内存中复制字符串数据,还是引用原始数据?例如,我是否应该担心$str = substr($str, 1);在循环中调用?

4

3 回答 3

4

如果你真的在研究效率,你需要在你的字符串中保留一个指针——我的意思是索引。许多字符串函数接受一个偏移量来开始操作(如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
    # ...
}
于 2010-05-11T18:02:59.007 回答
3

为了进一步 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  :-(
于 2010-05-11T18:13:36.097 回答
1

是的,您应该小心在循环内进行任何字符串操作,因为每次迭代都会生成字符串的新副本。

于 2010-05-11T17:53:36.880 回答