Upgrade to Pro — share decks privately, control downloads, hide ads and more …

How Doctrine caching can skyrocket your applica...

How Doctrine caching can skyrocket your application (SymfonyCon Amsterdam 2019)

When people talk about Doctrine (or any ORM for that matter), the performance issue always comes up fairly quickly. Besides the fact that Doctrine will help you develop faster, so a little overhead doesn't really matter, there are numerous options to increase the performance of the application.

By understanding how the system works in the first place, a lot of issues can be avoided right away.

When you have done everything to avoid these pitfalls, you can bring in the big guns: caching. Doctrine has several caching mechanism and since Doctrine 2.5 "Second Level Cache" was added to our toolbox. After this talk, you should know what the impact is of every cache and how to use them.

Jachim Coudenys

November 21, 2019
Tweet

More Decks by Jachim Coudenys

Other Decks in Programming

Transcript

  1. HOW DOCTRINE HOW DOCTRINE HOW DOCTRINE HOW DOCTRINE HOW DOCTRINE

    HOW DOCTRINE HOW DOCTRINE HOW DOCTRINE HOW DOCTRINE HOW DOCTRINE HOW DOCTRINE HOW DOCTRINE HOW DOCTRINE HOW DOCTRINE HOW DOCTRINE HOW DOCTRINE CACHING CAN CACHING CAN CACHING CAN CACHING CAN CACHING CAN CACHING CAN CACHING CAN CACHING CAN CACHING CAN CACHING CAN CACHING CAN CACHING CAN CACHING CAN CACHING CAN CACHING CAN CACHING CAN SKYROCKET YOUR SKYROCKET YOUR SKYROCKET YOUR SKYROCKET YOUR SKYROCKET YOUR SKYROCKET YOUR SKYROCKET YOUR SKYROCKET YOUR SKYROCKET YOUR SKYROCKET YOUR SKYROCKET YOUR SKYROCKET YOUR SKYROCKET YOUR SKYROCKET YOUR SKYROCKET YOUR SKYROCKET YOUR APPLICATION APPLICATION APPLICATION APPLICATION APPLICATION APPLICATION APPLICATION APPLICATION APPLICATION APPLICATION APPLICATION APPLICATION APPLICATION APPLICATION APPLICATION Jachim Coudenys Jachim Coudenys Jachim Coudenys Jachim Coudenys Jachim Coudenys Jachim Coudenys Jachim Coudenys Jachim Coudenys @coudenysj - jachim.be @coudenysj - jachim.be @coudenysj - jachim.be @coudenysj - jachim.be @coudenysj - jachim.be @coudenysj - jachim.be @coudenysj - jachim.be @coudenysj - jachim.be [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected]
  2. HOW DOCTRINE HOW DOCTRINE HOW DOCTRINE HOW DOCTRINE HOW DOCTRINE

    HOW DOCTRINE HOW DOCTRINE HOW DOCTRINE HOW DOCTRINE HOW DOCTRINE HOW DOCTRINE HOW DOCTRINE HOW DOCTRINE HOW DOCTRINE HOW DOCTRINE HOW DOCTRINE CACHING CAN CACHING CAN CACHING CAN CACHING CAN CACHING CAN CACHING CAN CACHING CAN CACHING CAN CACHING CAN CACHING CAN CACHING CAN CACHING CAN CACHING CAN CACHING CAN CACHING CAN CACHING CAN SKYROCKET YOUR SKYROCKET YOUR SKYROCKET YOUR SKYROCKET YOUR SKYROCKET YOUR SKYROCKET YOUR SKYROCKET YOUR SKYROCKET YOUR SKYROCKET YOUR SKYROCKET YOUR SKYROCKET YOUR SKYROCKET YOUR SKYROCKET YOUR SKYROCKET YOUR SKYROCKET YOUR SKYROCKET YOUR APPLICATION APPLICATION APPLICATION APPLICATION APPLICATION APPLICATION
  3. HOW DOCTRINE HOW DOCTRINE HOW DOCTRINE HOW DOCTRINE HOW DOCTRINE

    HOW DOCTRINE HOW DOCTRINE HOW DOCTRINE HOW DOCTRINE HOW DOCTRINE HOW DOCTRINE HOW DOCTRINE HOW DOCTRINE HOW DOCTRINE HOW DOCTRINE HOW DOCTRINE CACHING CAN CACHING CAN CACHING CAN CACHING CAN CACHING CAN CACHING CAN CACHING CAN CACHING CAN CACHING CAN CACHING CAN CACHING CAN CACHING CAN CACHING CAN CACHING CAN CACHING CAN CACHING CAN SKYROCKET YOUR SKYROCKET YOUR SKYROCKET YOUR SKYROCKET YOUR SKYROCKET YOUR SKYROCKET YOUR SKYROCKET YOUR SKYROCKET YOUR SKYROCKET YOUR SKYROCKET YOUR SKYROCKET YOUR SKYROCKET YOUR SKYROCKET YOUR SKYROCKET YOUR SKYROCKET YOUR SKYROCKET YOUR APPLICATION APPLICATION APPLICATION APPLICATION APPLICATION APPLICATION If you're using Doctrine ORM. If you're using Doctrine ORM.
  4. OBJECT-RELATIONAL MAPPER ... is a programming technique for converting data

    between incompatible type systems using object-oriented programming languages. — https://en.wikipedia.org/wiki/Object-relational_mapping
  5. A Bug has a description, creation date, status, reporter and

    engineer A Bug can occur on different Products (platforms) A Product has a name. Bug reporters and engineers are both Users of the system. A User can create new Bugs. The assigned engineer can close a Bug. A User can see all his reported or assigned Bugs. Bugs can be paginated through a list-view. AN EXAMPLE MODEL: BUG TRACKER
  6. UNIT OF WORK Maintains a list of objects affected by

    a business transaction and coordinates the writing out of changes and the resolution of concurrency problems. — https://martinfowler.com/eaaCatalog/unitOfWork.html
  7. UNIT OF WORK Unit of Work pattern keep track of

    things to do with next flush no direct interaction
  8. IDENTITY MAP Ensures that each object gets loaded only once

    by keeping every loaded object in a map. Looks up objects using the map when referring to them. — https://martinfowler.com/eaaCatalog/identityMap.html
  9. IDENTITY MAP A man with two watches never knows what

    time it is Load data in the same in-memory object Sync to database correctly
  10. PROXIES (LAZY LOADING) An object that doesn't contain all of

    the data you need but knows how to get it. — https://martinfowler.com/eaaCatalog/lazyLoad.html
  11. CREATING Create new object (NEW) Persist the object (MANAGED) Flush

    the EM UoW calculates changes => INSERT SQL Transaction
  12. UPDATING Get the object (MANAGED) Change a property Persist the

    object (no-op) Flush the EM UoW calculates changes => UPDATE SQL Transaction
  13. DELETING Get the object (MANAGED) Ask for removal (REMOVED) Flush

    the EM UoW calculates changes => DELETE SQL Transaction
  14. NOTIFY http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/change-tracking-policies.html#notify http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/change-tracking-policies.html#notify use Doctrine\Common\NotifyPropertyChanged, Doctrine\Common\PropertyChangedListener; /** * @Entity *

    @ChangeTrackingPolicy("NOTIFY") */ class MyEntity implements NotifyPropertyChanged { private $listeners = array(); public function addPropertyChangedListener(PropertyChangedListener $listener) { $this->listeners[] = $listener; } }
  15. NOTIFY http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/change-tracking-policies.html#notify http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/change-tracking-policies.html#notify class MyEntity implements NotifyPropertyChanged { protected function

    onPropertyChanged($propName, $oldValue, $newValue) { if ($this->listeners) { foreach ($this->listeners as $listener) { $listener->propertyChanged($this, $propName, $oldValue, $newValue); } } } public function setData($data) { if ($data != $this->data) { $this->onPropertyChanged('data', $this->data, $data); $this->data = $data; } } }
  16. ALTERNATIVE QUERY RESULT FORMATS $dql = "SELECT b, e, r,

    p FROM Bug b JOIN b.engineer e ". "JOIN b.reporter r JOIN b.products p ORDER BY b.created DESC"; $query = $entityManager->createQuery($dql); $bugs = $query->getArrayResult(); foreach ($bugs as $bug) { echo $bug['description'] . " - " . $bug['created']->format('d.m.Y')."\n"; echo " Reported by: ".$bug['reporter']['name']."\n"; echo " Assigned to: ".$bug['engineer']['name']."\n"; foreach ($bug['products'] as $product) { echo " Platform: ".$product['name']."\n"; } echo "\n"; }
  17. RESULT Store SQL data result to cache Still a need

    to hydrate objects Joins will be stored as-is*
  18. SECOND LEVEL SECOND LEVEL SECOND LEVEL SECOND LEVEL SECOND LEVEL

    SECOND LEVEL SECOND LEVEL SECOND LEVEL CACHING CACHING CACHING CACHING CACHING CACHING CACHING CACHING
  19. TYPES Entity data: id + values Collection data: ownerId id

    + list of ids Query data: list of ids
  20. REGIONS Every type has own region Can be configured Can

    be used for invalidation (specific entities) Own lifetime
  21. QUERY CACHE: DELETE / UPDATE QUERIES Directly into a database

    Bypass the second-level cache Entities that are already cached will NOT be invalidated Query hint
  22. CONCLUSION Keep Identity Map / internals in mind Using the

    basic caching (query + mapping) + opcode caching is a must Cache heavy queries with result cache Give Second Level Caching a try (even if only for entities) Query Cache !== Second Level Query Cache