TrogWarZ
@TrogWarZ
web developer

Апгрейд Phalcon 1.x до 2.x стал потреблять всю ОЗУ – как обойти?

Доброго времени!

Типичный ответ от API состоит из 100 объектов и + по 3 связанных объекта на каждый (итого ~400 минус дубли).
На Phalcon 1.3.6 API отвечает в пределах 1 секунды и потребляет несколько Мб памяти. XhProf утверждает, что тормоз – \file_exists в автолоадере композера (-:
На Phalcon 2.0.10 в том же запросе начинается жесть: API отвечает по 30-60 секунд и выедает всю доступную память (1 Гб ОЗУ + 1Гб свопа) и целое ядро ЦП. XhProf показывает, что тормозом является \ReflectionClass::getProperty, а следы ведут в \Phalcon\Mvc\Model\Resultset\Simple::current.

Кто-то с таким сталкивался? Есть решение/обход?

Повторяется на Ubuntu 12.x/14.x, PHP 5.5.x, PHP 5.6.x (`ppa:ondrej/php`), PHP 5.6.x (`ppa:ondrej/php5-5.6`, deprecated).

ps: к сожалению, выделить из проекта thephpleague/fractal так чтобы сформировать точно такой же ответ для этого запроса – слишком затратно по времени и не очень понятно. Я, конечно, могу использовать \Phalcon\PDO::execute() и одним SQL-запросом выбрать все нужные данные, но уверен – это не покажет ничего о причинах тормозов после апгрейда.

UPD: https://github.com/phalcon/cphalcon/pull/12131 – Этот PR, видимо, будет вмержен в 3.0.1 и исправляет САБЖ.
  • Вопрос задан
  • 515 просмотров
Решения вопроса 1
Yeah
@Yeah
В рамках вот этого пулл-реквеста добавлена проверка на видимость полей через Reflection. В 1.3.2 такой функциональности не было, потому и работало быстро.

Что характерно, версия 1.x использовала для этого метод getModelsMetadata, который возвращал данные о полях (которые, к слову, еще и кешировал), а в 2.x это убрали и добавили тупое обращение к Reflection. Для production-ready high-speed фреймворка - это дичайший зашквар.

В качестве ответа на вопрос, что делать, могу посоветовать: определяйте сеттеры. Тогда код зайдет в блок _possibleSetter и до _isVisible выполнение не дойдет. Это костыль, но должно сработать.

Еще можно переопределить __set в своем базовом классе модели. Что-то типа:

public function __set($property, $value) {
    if (is_array($value) || is_object($value)) {
        return parent::__set($property, $value);
    }
    if ($this->_possibleSetter($property, $value)) {
        return $value();
    }
    $this->{$property} = $value;
    return $value();
}


Но это на свой страх и риск, так как валидность свойств проверяться не будет.

Ну и пишите им issue, конечно
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы