Skip to content
debesha edited this page Jul 23, 2015 · 7 revisions

Why do you need this bundle?

Let’s say you have related entities - product and productHistoricPrice, which holds an information about product’s price in any day in the past. Relation is one-to-many, and entities are described like this:

/**
 * @ORM\Entity
 */
class Product
{
    /**
     * @ORM\OneToMany(targetEntity="ProductHistoricPrice", mappedBy="product", indexBy="date")
     */
    protected $historicPrices;

    public function __construct()
    {
        $this->historicPrices = new Doctrine\Common\Collections\ArrayCollection();
    }
...
    public function getPriceByDate($date) {

        return $this->historicPrices[$date];
    }
}
/**
 * @ORM\Entity
 */

class ProductHistoricPrice {

    /**
     * @ORM\ManyToOne(targetEntity="Product", inversedBy="historicPrices")
     * @ORM\JoinColumn(name="id_product", referencedColumnName="id")
     */
    protected $product;
}

Now if you would make a call somewhere in your application $someProduct->getPriceByDate($someDate); Doctrine will extract from database all prices for the product, unless the price was extracted in advance. Which is OK, it’s supposed to work like this, it’s lazy load. But it’s not what you need in this case, you needed only 1 price. And in this case, you’ll face overuse of resources. And what is even worse - it’s very hard to see it via Symfony WebProfiler.

So an example from real life.

I was making a REST API and for a not very difficult request I’ve noticed the response is very slow - 7.2 sec.

(image::https://habrastorage.org/files/5bf/1d7/77c/5bf1d777c62c46b2abec63c2fcab7ca2.png[Slow AJAX call])

Often SQL requests are what slow down an application, but not in this case - 223ms for all requests.

SQL requests are fast

When you look at a timeline, you see that problems arise somewhere in the controller, but it’s absolutely not clear where precisely.

Timeline

Like you have already probably guessed, the problem was in overuse of resources while unused objects were hydrated from DB. But you can’t say by the profiler.

Unless you have DoctrineProfileExtraBundle.

It tracks information how much time and how many entities were hydrated by Doctrine ORM.

And with the information described problem with performance become very easy to spot -

new hydration panel

For the same call now I see that 5.4 sec was spent on a hydration of objects, and there are hundreds of them (and majority stay unused).

After very little tweaks in code it became way more faster:

after an optiomization
Clone this wiki locally