Страницы

Поиск по вопросам

суббота, 7 марта 2020 г.

Потребление памяти PHP-генераторами

#php


В документации говорится:


  Генератор позволяет Вам писать код, использующий foreach для перебора набора данных
без необходимости создания массива в памяти, что может привести к превышению вами лимита
памяти, либо потребует довольно много времени для его создания. Вместо этого, Вы можете
написать функцию-генератор, которая, по сути, является обычной функцией, за исключением
того, что вместо возвращения единственного значения, генератор может yield столько
раз, сколько необходимо для генерации значений, позволяющих перебрать исходный набор
данных.
  
  Наглядным примером вышесказанного может послужить использование функции range()
как генератора. Стандартная функция range() должна генерировать массив, состоящий из
значений, и возвращать его, что может послужить результатом генерации огромных массивов:
например, вызов range(0, 1000000), приведёт к использованию более чем 100 МБ памяти.
  
  В качестве альтернативы мы можем создать генератор xrange(), который использует
память только для создания объекта Iterator и сохранения текущего состояния, что потребует
не больше 1 килобайта памяти.





  A generator allows you to write code that uses foreach to iterate over a set of
data without needing to build an array in memory, which may cause you to exceed a memory
limit, or require a considerable amount of processing time to generate. Instead, you
can write a generator function, which is the same as a normal function, except that
instead of returning once, a generator can yield as many times as it needs to in order
to provide the values to be iterated over.
  
  A simple example of this is to reimplement the range() function as a generator.
The standard range() function has to generate an array with every value in it and return
it, which can result in large arrays: for example, calling range(0, 1000000) will result
in well over 100 MB of memory being used.
  
  As an alternative, we can implement an xrange() generator, which will only ever
need enough memory to create an Iterator object and track the current state of the
generator internally, which turns out to be less than 1 kilobyte.




И приводится пример:

function xrange($start, $limit, $step = 1) {
    if ($start < $limit) {
        if ($step <= 0) {
            throw new LogicException('Step must be +ve');
        }

        for ($i = $start; $i <= $limit; $i += $step) {
            yield $i;
        }
    } else {
        if ($step >= 0) {
            throw new LogicException('Step must be -ve');
        }

        for ($i = $start; $i >= $limit; $i += $step) {
            yield $i;
        }
    }
}

/*
 * Note that both range() and xrange() result in the same
 * output below.
 */

echo 'Single digit odd numbers from range():  ';
foreach (range(1, 9, 2) as $number) {
    echo "$number ";
}
echo "\n";

echo 'Single digit odd numbers from xrange(): ';
foreach (xrange(1, 9, 2) as $number) {
    echo "$number ";
}




Я увеличил количество генераций до 100000:


range(): https://repl.it/Fy4I;
xrange(): https://repl.it/Fy4K.


Результат мало чем отличается. Я полагал, что при использовании xrange() памяти должно
быть потреблено меньше. Почему так?
    


Ответы

Ответ 1



Потому, что вы забыли использовать результат Надо так: $a=range(0, 100000); 4474.390625 https://repl.it/Fy4I/1 Создался полный набор значений. $a=xrange(0, 100000); 377.7890625 https://repl.it/Fy4K/1 Извлечено только одно значение.

Комментариев нет:

Отправить комментарий