Нещодавно я реалізував функції API в проекті з бек-ендом Symfony2, що використовує Doctrine в якості ORM.
І, як це іноді буває, швидкість відпрацьовування не цілком мене влаштувала. На нескладний запит відповідь генерувалася аж 7,2 сек.
Перше припущення, десь запускаються якісь важкі запити. Але через профайлер не видно нічого такого, що могло б
навести на думку про те, де зникла проблема. SQL-запитів забагато, але всі швидкі, і загальний їх час виконання всього 223 мілісекунди.
Іду в закладку Timeline - видно, що проблема виникає під час роботи контролера (там буквально 5 рядків), але де саме - ясніше не стало.
Що виявилося в підсумку.
Виявилося, що для генерації даних деякі моделі (в глибині давно написаних сервісів) вимагали пов'язані one-to-many об'єкти. Об'єкт потрібен був один, але для доступу до нього піднімався весь ArrayCollection із сотень об'єктів.
Тобто. деякі з тих швидких запитів повертали сотні рядків, на основі яких Doctrine піднімав сотні об'єктів, і на це йшла безліч ресурсів.
Проблема ця вирішилася просто. Трохи скоригувавши логіку моделей, до моменту звернення до зв'язаних об'єктів я їх вже готував. Час роботи став прийнятним. Але проблема, при цьому, як мені здається, може бути досить типовою і виникати часто в проектах, пов'язаних з Doctrine. Потрібен один прив'язаний об'єкт, ініціалізуються (не дуже помітно для розробника) всі.
Добре б все-таки це якось контролювати.
Тому я зробив бандл, який збирає дані про час гідрації об'єктів всередині Doctrine.
Думаю, може бути корисним для будь-якого проекту, що використовує зв'язку Symfony2 + Doctrine2.
debesha/DoctrceProfileExtraBundle (гітхаб)
Після встановлення бандла в панелі профайлера з'являється додатковий бадж, в якому видно, скільки було виконано гідрацій і скільки на це було витрачено часу:
Відповідно, профайлер у прикладі, який я навів на початку, виглядає вже більш красномовно - на гідрацію об'єктів витрачено 5,5 секунд.
І те ж саме, але після оптимізації (яка, як я вже сказав, була дуже простою. Найскладніше було локалізувати проблему).
Гідрація зайняла 0.4 секунди (на моєму повільному робочому компі).
Сподіваюся своїм бандлом я зекономлю комусь із колег купу часу.
