PHP сборка мусора и оптимизация памяти - PullRequest
2 голосов
/ 25 февраля 2012

Я делаю некоторые тесты памяти PHP и мне интересно, есть ли способ оптимизировать сборщик мусора, чтобы уменьшить потребление памяти (как это возможно в других языках, таких как JAVA).

Я нашел только три настраиваемых параметра, связанных с GC, в php.ini: session.gc_probability, session.gc_divisor и session.gc_maxlifetime. Это только для сессий, и я не проверяю это.

Возможные оптимизации, которые я знаю до сих пор, связаны с кодом, например, избегание циклических ссылок и форсирование цикла сбора мусора путем вызова gc_collect_cycles() (благодаря этой статье http://www.alexatnet.com/comment/86).

Кто-нибудь знает какие-либо приемы настройки или передовые практики в управлении памятью PHP?

Ответы [ 3 ]

4 голосов
/ 25 февраля 2012

Насколько я знаю, форсирование коллекции с помощью gc_collect_cycles() - самое близкое к тому, что вы можете минимизировать использование памяти в момент времени t.

GC, конечно, является операцией с ограничением по времени, и приложение редко имеет критическую привязку к памяти, и поэтому не имеет смысла предлагать опции для ненужного запуска прогонов GC на протяжении всего выполнения программы. В этом ключе PHP предлагает возможность включать и выключать сборщик циклов по требованию (gc_enable(), gc_disable()), так что вы можете оптимизировать свой код на время (избегая накладных расходов GC). решив начать) - конечно, легко понять, как это может быть полезно.

В целом, PHP по философии избегает таких тем, как управление памятью и сборщик мусора, и ваши тесты, возможно, должны учитывать это для более реальной перспективы.

Надеюсь, это поможет.

(К тому же, комментарий к GordonM со ссылкой на микрооптимизацию).

1 голос
/ 07 июля 2017

В общем, управление памятью PHP работает "из коробки" для всех переменных, которые вы объявляете и используете.Используя концепцию пересчета, PHP видит, что переменная больше не используется, а затем автоматически очищает ее.

Сборщик мусора интересен только для случаев, когда объекты имеют циклические ссылки, A указывает на B, B указывает назадA. В этом случае пересчет не работает.

Если в памяти PHP ровно 10.000 объектов, которые потенциально цикличны и потенциально больше не используются, тогда сборщик мусора PHP запускает его, если он включенпо умолчанию.Вы можете отключить или включить его с помощью gc_enable() и gc_disable() во время выполнения.

Вы также можете вызвать gc_collect_cycles() для очистки этих объектов вручную.

Но как оптимизировать этот процесс, есливам нужно?Запуск сборщика циклов не должен быть эффективным или полезным из 10 000 потенциальных объектов, многие из которых все еще могут использоваться и не могут быть очищены.В этом случае вы тратите циклы ЦП на проверку всех объектов и решаете не очищать их.Если вы сделаете это, никакого сокращения памяти не будет.

Обычно сборщик мусора запускается только в долго выполняющихся скриптах и ​​только иногда в коротких веб-запросах, когда они создают слишком много объектов.В общем, вы не должны слишком много думать об этом, потому что настройки по умолчанию работают для 99% сценариев использования.

С расширением PHP "garbage_stats" вы можете получить доступ к метрикам и статистике о том, насколько эффективно и быстроGC побежал и сколько памяти было уменьшено.Он работает на PHP 7+ (потому что перехватчики доступны только с тех пор): https://github.com/tideways/php_garbage_stats

Если вы установили расширение, вы можете просмотреть статистику сборки мусора для сценариев CLI, вызвав их:

$ php -dgc_stats.enable=1 -dgc_stats.show_report=1 test.php

Found 7 garbage collection runs in current script.

Collected | Efficency% | Duration | Memory Before | Memory After | Reduction% | Function
----------|------------|----------|---------------|--------------|------------|---------
        0 |     0.00 % |  0.01 ms |        365824 |       366320 |    -0.14 % | gc_collect_cycles
    10000 |   100.00 % |  2.75 ms |       4651320 |       491816 |    89.43 % | foo
    10000 |   100.00 % |  3.54 ms |       4652784 |       493280 |    89.40 % | foo
    10000 |   100.00 % |  2.11 ms |       4654248 |       494744 |    89.37 % | foo
    10000 |   100.00 % |  3.26 ms |       4656168 |       496664 |    89.33 % | Test::foo
     9000 |    90.00 % |  1.51 ms |       4694680 |       951176 |    79.74 % | Test::foo
    10000 |   100.00 % |  3.11 ms |       5112272 |       952768 |    81.36 % | Test::foo

Из веб-запроса (например, Apache или FPM) вы можете использовать функцию $runs = gc_stats(); для доступа к этой информации и записи ее в файл журнала.

на основе этой информации вы можете сделатьединственное решение, которое можно оптимизировать: включить или отключить сборщик мусора в сценарии в зависимости от его эффективности.

0 голосов
/ 25 февраля 2012

Я использую метод unset (), чтобы очистить переменную, когда она мне больше не нужна.

...