(В частности, я работаю внутри Magento, но это общий вопрос PHP.)
У меня есть одноэлементный класс с массивом, который хранит большие объекты. Пожалуйста, примите во внимание следующее:
protected $_categoryObjectCache = array();
/**
* @param $key
* @param $value
*/
public function setCategoryObjectCache($key, $value) {
$this->_categoryObjectCache[$key] = $value;
if ($this->nearingMemoryLimit()) {
unset($this->_categoryObjectCache);
if (function_exists('gc_collect_cycles')) {
gc_collect_cycles();
}
$this->_categoryObjectCache = array();
}
}
/**
* @return bool
*/
protected function nearingMemoryLimit() {
$memory_limit = ini_get('memory_limit');
if (preg_match('/^(\d+)(.)$/', $memory_limit, $matches)) {
if ($matches[2] == 'M') {
$memory_limit = $matches[1] * 1024 * 1024; // nnnM -> nnn MB
} else if ($matches[2] == 'K') {
$memory_limit = $matches[1] * 1024; // nnnK -> nnn KB
}
}
return ((memory_get_usage() / $memory_limit) > 0.75);
}
(Метод setCategoryObjectCache()
не очень часто звонят. Обычно я просто читаю из этого массива методом getCategoryObjectCache()
)
Я создал этот одноэлементный кеш как часть импортера, который просматривает тысячи продуктов и распределяет их по различным категориям. Однако это требует загрузки каждой модели категории и использования ее встроенных методов для поиска родительских / дочерних отношений, статуса и т. Д. Поиск каждой категории, к которой продукт хочет относиться, много раз для каждого продукта, вызвавшего тысячи повторяющихся экземпляров модели. для той же категории. Этот кеш решает эту проблему.
Однако проблема в том, что я беспокоюсь о том, что кеш становится слишком большим. Magento известен своими проблемами с производительностью из-за этих огромных модельных объектов. Поэтому я написал приведенный выше код, чтобы посмотреть текущее использование памяти сценариями и очистить кэш, если сценарий слишком близок к максимальному использованию памяти.
То, что я не знаю, действительно ли это сработает. Сборка мусора в PHP — большая загадка для меня, и я не уверен, что могу просто позвонить $this->_categoryObjectCache = array();
и ожидайте, что PHP очистит, или если мне действительно нужно было позвонить unset($this->_categoryObjectCache);
а также gc_collect_cycles();
Как я могу убедиться, что очистил ОЗУ, когда мой кэш начинает становиться слишком большим?
Задача ещё не решена.
Других решений пока нет …