Я пишу синтаксический анализатор в PHP, который должен смочь обработать большие строки в оперативной памяти, таким образом, это - несколько важная проблема. (т.е., не делайте "преждевременный, оптимизируют" пламя меня),
Как делает substr
функциональная работа? Это делает вторую копию строковых данных в памяти, или действительно ли это ссылается на оригинал? Если я волнуюсь о вызове, например, $str = substr($str, 1);
в цикле?
В продолжение комментария Чада, ваш код требует, чтобы обе строки (полная и полная минус первый символ) находились в памяти одновременно (хотя и не из-за присваивания, как указал Чад). Смотрите:
$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 :-(
Если вы действительно хотите повысить эффективность, вам нужно будет сохранить указатель - я имею в виду 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
# ...
}
Да, вы должны быть осторожны, выполняя любые манипуляции со строкой внутри цикла, поскольку на каждой итерации будут создаваться новые копии строки.