PHP'的效率如何;什么是substr?

PHP'的效率如何;什么是substr?,php,optimization,memory-management,substr,Php,Optimization,Memory Management,Substr,我正在用PHP编写一个解析器,它必须能够处理内存中的大字符串,所以这是一个有点重要的问题。(即,请不要“过早”解雇我) substr功能是如何工作的?它是在内存中复制字符串数据的第二个副本,还是引用原始数据?我是否应该担心调用,例如,$str=substr($str,1)在循环中?是的,在循环中进行任何字符串操作时都应该小心,因为每次迭代都会生成新的字符串副本。如果您真的在考虑效率,您需要在字符串中保留一个指针(我是指索引)。许多字符串函数接受开始操作的偏移量(如的第三个参数)。通常我会建议编写

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


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

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

如果您真的在考虑效率,您需要在字符串中保留一个指针(我是指索引)。许多字符串函数接受开始操作的偏移量(如的第三个参数)。通常我会建议编写一个对象来包装此功能,但如果您希望大量使用此功能,则可能会导致性能瓶颈。下面是我的意思(没有OO)的一个例子:

如果需要,您可以编写自己的包装器类来执行这些字符串操作,并查看它是否对速度有影响:

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所述的赋值)。见:

输出类似(内存值以字节为单位):


我认为任务是杀手,而不是替补。扩展可能会有所帮助,但它需要在php中启用。我不是php爱好者,所以您可以简单地说不。在Java中,它只创建对同一个不可变字符数组的新引用。因此,虽然它创建了一个新的字符串对象,但它不会存储底层字符数组的更多副本。它只是声明偏移量是不同的。php是否真的创建了char数组的新副本?或者只引用同一个字符数组。普通Java字符串会自动执行这些操作。为什么PHP没有?
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
    # ...
}
$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  :-(