Насколько эффективен субстрат PHP? - PullRequest
7 голосов
/ 11 мая 2010

Я пишу парсер на PHP, который должен уметь обрабатывать большие строки в памяти, так что это довольно важный вопрос. (то есть, пожалуйста, не «преждевременно оптимизируйте» меня, пожалуйста)

Как работает функция substr? Делает ли он вторую копию строковых данных в памяти или ссылается на оригинал? Стоит ли беспокоиться о вызове, например, $str = substr($str, 1); в цикле?

Ответы [ 3 ]

4 голосов
/ 11 мая 2010

Если вы действительно ищете эффективность, вам нужно сохранить указатель - я имею в виду index - с вашей строкой.Многие строковые функции принимают смещение для начала работы (например, третий параметр 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
    # ...
}
3 голосов
/ 11 мая 2010

Для дальнейшего комментария Чада, ваш код потребовал бы, чтобы обе строки (полная и полная-один-минус первый символ) были в памяти одновременно (хотя не из-за назначения, как сказал Чад) , См:

$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  :-(
1 голос
/ 11 мая 2010

Да, вы должны быть осторожны при выполнении любых операций со строками внутри цикла, так как новые копии строки будут генерироваться на каждой итерации.

...