SlideShare uma empresa Scribd logo
1 de 66
Baixar para ler offline
Effective Doctrine2
Performance Tips for Symfony2 Developers
Wrocław Symfony Group #2 April 24th, 2014
Effective Doctrine2: Performance Tips for Symfony2 Developers marcin.chwedziak
Who am I?
Effective Doctrine2: Performance Tips for Symfony2 Developers marcin.chwedziak
Symfony2 ContributorSilex Contributor
Symfony2 Developer
Angular.jsDeveloper
AgileEnthusiast
„No worries, I will handle this”
AppreciatedContractor
Marcin Chwedziak
github.com/tiraeth
lnkd.in/dp6sPzc
Software Engineer at Spork Labs LLP (Salt Lake City, UT)
Effective Doctrine2: Performance Tips for Symfony2 Developers marcin.chwedziak
What is this talk about?
Effective Doctrine2: Performance Tips for Symfony2 Developers marcin.chwedziak
plus things that can go wrong while working with Symfony2
107 queries executed in 17.25 seconds
Effective Doctrine2: Performance Tips for Symfony2 Developers marcin.chwedziak
While working with databases,
the most important strategy is
to avoid querying a database.
Effective Doctrine2: Performance Tips for Symfony2 Developers marcin.chwedziak
Rule #1: Caching
Effective Doctrine2: Performance Tips for Symfony2 Developers marcin.chwedziak
If you must query a database,
be wise and do it smarter.
Effective Doctrine2: Performance Tips for Symfony2 Developers marcin.chwedziak
Rule #2: Code Optimization
Effective Doctrine2: Performance Tips for Symfony2 Developers marcin.chwedziak
Smart behaviour also means
to be explicit in actions.
Effective Doctrine2: Performance Tips for Symfony2 Developers marcin.chwedziak
Rule #3: Transaction Demarcation
Effective Doctrine2: Performance Tips for Symfony2 Developers marcin.chwedziak
Caching w/ Doctrine2
Effective Doctrine2: Performance Tips for Symfony2 Developers marcin.chwedziak
Metadata
What can be effectively cached?
Query Result
Effective Doctrine2: Performance Tips for Symfony2 Developers marcin.chwedziak
Parsing model metadata from different sources with
each request can have a serious impact on your
application’s performance. It is a good practice to
cache it.
Effective Doctrine2: Performance Tips for Symfony2 Developers marcin.chwedziak
Each time you write a DQL query or use the
QueryBuilder to create one, Doctrine has to
transform that query to SQL. This is an unnecessary
waste of available resources.
Effective Doctrine2: Performance Tips for Symfony2 Developers marcin.chwedziak
Usually, there is no special reason to hit a database
for rarely modified data. Configure Result Cache
strategy to make sure that your database is not
swamped with such queries.
Effective Doctrine2: Performance Tips for Symfony2 Developers marcin.chwedziak
Be aware!
Make sure you properly create your queries.
Effective Doctrine2: Performance Tips for Symfony2 Developers marcin.chwedziak
# Fetch expired subscriptions (non-cachable)
SELECT s
FROM ASBillingBundle:Subscription s
WHERE s.validTo < ?
[1397855248]
!
# Fetch expired subscriptions (cachable)
SELECT s
FROM ASBillingBundle:Subscription s
WHERE s.validTo < CURRENT_TIMESTAMP()
You can cache both DQL and Native SQL queries.
Effective Doctrine2: Performance Tips for Symfony2 Developers marcin.chwedziak
How to cache metadata in Symfony2?
Effective Doctrine2: Performance Tips for Symfony2 Developers marcin.chwedziak
app/config/config_prod.yml
doctrine:
orm:
# ...
metadata_cache_driver: apc
# ...
Effective Doctrine2: Performance Tips for Symfony2 Developers marcin.chwedziak
Can I implement custom caching service?
Effective Doctrine2: Performance Tips for Symfony2 Developers marcin.chwedziak
app/config/config_prod.yml
doctrine:
orm:
# ...
metadata_cache_driver:
type: service
id: as.doctrine.cache.couchbase
# ...
Effective Doctrine2: Performance Tips for Symfony2 Developers marcin.chwedziak
src/AS/CoreBundle/Doctrine/Cache/CouchbaseCache.php
<?php
!
namespace AS/CoreBundle/Doctrine/Cache;
!
use DoctrineCommonCacheCacheProvider;
!
class CouchbaseCache extends CacheProvider

{
// doFetch($id)
// doContains($id)
// doSave($id, $data, $liteTime = 0)
// doDelete($id)
// doFlush()
// doGetStats()
}
Effective Doctrine2: Performance Tips for Symfony2 Developers marcin.chwedziak
How to cache queries in Symfony2?
Effective Doctrine2: Performance Tips for Symfony2 Developers marcin.chwedziak
app/config/config_prod.yml
doctrine:
orm:
# ...
query_cache_driver: apc
# ...
Effective Doctrine2: Performance Tips for Symfony2 Developers marcin.chwedziak
How to cache query results in Symfony2?
Effective Doctrine2: Performance Tips for Symfony2 Developers marcin.chwedziak
app/config/config_prod.yml
doctrine:
orm:
# ...
result_cache_driver: apc
# ...
Effective Doctrine2: Performance Tips for Symfony2 Developers marcin.chwedziak
Setting caching driver for Query Result Cache is not
sufficient for enabling the strategy. You need to
explicitly enable it for each and every query you’re
interested in.
Effective Doctrine2: Performance Tips for Symfony2 Developers marcin.chwedziak
<?php
!
// ...
!
$query = $em->createQuery($dql);
$query->useResultCache(true);
!
// …
Effective Doctrine2: Performance Tips for Symfony2 Developers marcin.chwedziak
With great power comes great responsibility.
Voltaire (1694-1778)
Effective Doctrine2: Performance Tips for Symfony2 Developers marcin.chwedziak
Be aware that high traffic websites can generate
races while accessing cached data. This situation is
called cache slam. When implementing own cache
driver, please refer to your backend’s documentation
regarding races avoidance.
Effective Doctrine2: Performance Tips for Symfony2 Developers marcin.chwedziak
If anything goes wrong, you can manually clear the
cache without restarting/flushing the storage.
php app/console doctrine:cache:clear-metadata
php app/console doctrine:cache:clear-query
php app/console doctrine:cache:clear-result
Effective Doctrine2: Performance Tips for Symfony2 Developers marcin.chwedziak
Optimization Guidelines
Effective Doctrine2: Performance Tips for Symfony2 Developers marcin.chwedziak
You can begin your journey with code optimization
while using Doctrine2 with properly set up domain
models.
Please be aware that the following guidelines are for
use with Doctrine2, not necessarily with database
design in general.
Effective Doctrine2: Performance Tips for Symfony2 Developers marcin.chwedziak
Step 1: Avoid bidirectional associations
Effective Doctrine2: Performance Tips for Symfony2 Developers marcin.chwedziak
If you really need bidirectional associations, try to
use lazy fetching strategy, but in most cases
bidirectional relations are not necessary and should
be avoided.
Effective Doctrine2: Performance Tips for Symfony2 Developers marcin.chwedziak
Be aware that lazy fetching strategy creates
dynamic proxy objects (class is generated on the
fly).
Fortunately, Symfony2 handles proxy generation
with cache warmup task.
Effective Doctrine2: Performance Tips for Symfony2 Developers marcin.chwedziak
For aggregations (with Collections) you can use
EXTRA LAZY strategy which will not load the whole
collection on first access, as it is done in LAZY
strategy.
Effective Doctrine2: Performance Tips for Symfony2 Developers marcin.chwedziak
Dropping such relations does not mean that you
can’t use JOIN with your DQL / Native SQL queries.
Effective Doctrine2: Performance Tips for Symfony2 Developers marcin.chwedziak
<?php
!
namespace ASBillingBundleEntity;
!
class Subscription
{
/**
* @ORMManyToOne(targetEntity="User")
* @ORMJoinColumn(name="user_id", referencedColumnName="id")
*/
protected $user;
}
!
!
!
class User
{
// ...
}
Effective Doctrine2: Performance Tips for Symfony2 Developers marcin.chwedziak
SELECT u
FROM ASBillingBundle:User u
JOIN ASBillingBundle:Subscription s WITH s.user = u
WHERE s.validTo <= CURRENT_DATE()
Effective Doctrine2: Performance Tips for Symfony2 Developers marcin.chwedziak
Step 2: Avoid unnecessary cascades
Effective Doctrine2: Performance Tips for Symfony2 Developers marcin.chwedziak
1. Do not configure cascade operations on every
association you have in your domain.
2. Unless required (e.g. additional file removal), use
DBMS cascades instead of ORM ones.
Effective Doctrine2: Performance Tips for Symfony2 Developers marcin.chwedziak
Remember that you do not setup ORM cascades on
target entites but on the triggering ones. Opposite
to DBMS configuration.
Effective Doctrine2: Performance Tips for Symfony2 Developers marcin.chwedziak
<?php
!
namespace ASBillingBundleEntity;
!
class Subscription
{
/**
* @ORMOneToOne(targetEntity="User", cascade={"remove"})
* @ORMJoinColumn(name="user_id", referencedColumnName="id")
*/
protected $user;
}
This is wrong:
Effective Doctrine2: Performance Tips for Symfony2 Developers marcin.chwedziak
<?php
!
namespace ASBillingBundleEntity;
!
class Subscription
{
/**
* @ORMManyToOne(targetEntity="User")
* @ORMJoinColumn(
* name="user_id",
* referencedColumnName="id",
* onDelete="CASCADE"
* )
*/
protected $user;
}
This is correct:
Effective Doctrine2: Performance Tips for Symfony2 Developers marcin.chwedziak
Step 3: Avoid lifecycle events abuse
Effective Doctrine2: Performance Tips for Symfony2 Developers marcin.chwedziak
Be smart about listening to lifecycle events like
persist, update, or remove. Know the difference
between Listener and Subscriber.
Do not identify Doctrine2 event subscribers with
Symfony2 subscribers, which are more dynamic!
Effective Doctrine2: Performance Tips for Symfony2 Developers marcin.chwedziak
Avoid requiring EntityManager in your event
listeners (it will just not work).
Effective Doctrine2: Performance Tips for Symfony2 Developers marcin.chwedziak
<?php
!
namespace ASBillingBundleListener;
!
use SymfonyBridgeDoctrineRegistryInterface;
!
abstract class LifecycleListener
{
protected $doctrine;
protected $manager;
!
public function __construct(
RegistryInterface $doctrine,
$manager = 'default'
) {
$this->doctrine = $doctrine;
$this->manager = $manager;
}
!
protected function getEntityManager()
{
return $this->doctrine->getEntityManager($this->manager);
}
}
Effective Doctrine2: Performance Tips for Symfony2 Developers marcin.chwedziak
Step 4: Load from database what you need
Effective Doctrine2: Performance Tips for Symfony2 Developers marcin.chwedziak
Fetch
Modes
Return only data you are in need of.
Hydration
Modes
Partial
Objects
Effective Doctrine2: Performance Tips for Symfony2 Developers marcin.chwedziak
When dealing with one-to-one and many-to-one
relations, you can switch between EAGER and LAZY
fetching modes right in your Query object.
<?php
!
$query = $em->createQuery(
"SELECT s FROM ASBillingBundle:Subscription s"
)
->setFetchMode(
"ASBillingBundle:Subscription",
"user",
DoctrineORMMappingClassMetadata::FETCH_EAGER
);
Effective Doctrine2: Performance Tips for Symfony2 Developers marcin.chwedziak
If not necessary, do not fetch a whole object (with
relations) to just get its „validTo” field value.
<?php
!
$expirationDate = $em->createQuery(
"SELECT s.validTo " .
"FROM ASBillingBundle:Subscription s " .
"WHERE s.user = ?1"
)
->setParameter(1, $user)
->getSingleScalarResult();
Effective Doctrine2: Performance Tips for Symfony2 Developers marcin.chwedziak
Unless you can deal with scalar values or arrays, you
may need to wrap data in your model’s class. Use
Partial Objects for this purpose.
<?php
!
$reference = $em->createQuery(
"SELECT PARTIAL s.{plan,validTo} " .
"FROM ASBillingBundle:Subscription s " .
"WHERE s.id = ?1"
)->setParameter(1, $id)->getResult();
!
$reference->getPartialReference("ASBillingBundle:Subscription", $id);
Effective Doctrine2: Performance Tips for Symfony2 Developers marcin.chwedziak
Step 4: Load from database when you need
Effective Doctrine2: Performance Tips for Symfony2 Developers marcin.chwedziak
If you have to process data for large result sets,
think about using DQL UPDATE/DELETE queries or
Iterable Result.
When using Iterable Result always remember to
detach all existing and not required anymore objects
from Doctrine!
Effective Doctrine2: Performance Tips for Symfony2 Developers marcin.chwedziak
<?php
!
$batch = 50;
$i = 0;
!
$iterableResult = $em->createQuery(
"SELECT s FROM ASBillingBundle:Subscription s"
)->iterate();
!
foreach ($iterableResult as $row) {
$subscription = $row[0];
$subscription->renew();
if (($i % $batch) === 0) {
$em->flush(); // Execute queued updates
$em->clear(); // Detach objects and GC them
}
++$i;
}
!
$em->flush(); // Execute remainig updates
$em->clear(); // Detach remaining objects and GC them
Effective Doctrine2: Performance Tips for Symfony2 Developers marcin.chwedziak
<?php
!
$iterableResult = $em->createQuery(
"SELECT s FROM ASBillingBundle:Subscription s " .
"WHERE s.validTo = CURRENT_DATE() AND s.trialing = TRUE"
)->iterate();
!
foreach ($iterableResult as $row) {
$mailer->notifyTrialExpiration($row[0]);
$em->detach($row[0]); // Detach and GC immediately
}
Effective Doctrine2: Performance Tips for Symfony2 Developers marcin.chwedziak
Transaction Demarcation
Effective Doctrine2: Performance Tips for Symfony2 Developers marcin.chwedziak
Proper transaction boundary definition can have
positive impact on your application’s performance.
Doctrine2 takes care of proper implicit demarcation
for UnitOfWork–handled objects and queue all
operations until EntityManager#flush() is invoked.
Effective Doctrine2: Performance Tips for Symfony2 Developers marcin.chwedziak
However, Doctrine2 encourages developers to take
over and control transaction demarcation tasks
themselves.
Please remember to flush the EntityManager prior to
transaction commit. In case of any exceptions,
always close the EntityManager.
Effective Doctrine2: Performance Tips for Symfony2 Developers marcin.chwedziak
<?php
!
$em->getConnection()->beginTransaction();
!
try {
$user = new User;
$subscription = new Subscription;
$subscription->setUser($user);
!
// ... do some work
!
$em->persist($user);
$em->persist($subscription);
$em->flush();
$em->getConnection()->commit();
} catch (Exception $e) {
$em->getConnection()->rollback();
$em->close();
!
// ... do something about the exception
}
Effective Doctrine2: Performance Tips for Symfony2 Developers marcin.chwedziak
<?php
!
$em->transactional(function($em) {
$user = new User;
$subscription = new Subscription;
$subscription->setUser($user);
!
// ... do some work
!
$em->persist($user);
$em->persist($subscription);
});
Using EntityManager#transactional() will automatically flush the
manager prior to commit.
Effective Doctrine2: Performance Tips for Symfony2 Developers marcin.chwedziak
<?php
!
$em->getConnection()->transactional(function($em) {
$user = new User;
$subscription = new Subscription;
$subscription->setUser($user);
!
// ... do some work
!
$em->persist($user);
$em->persist($subscription);
$em->flush();
});
Warning! This will not close EntityManager on exception.
Thank you!
Wrocław Symfony Group #2 April 24th, 2014

Mais conteúdo relacionado

Mais procurados

Keeping it small: Getting to know the Slim micro framework
Keeping it small: Getting to know the Slim micro frameworkKeeping it small: Getting to know the Slim micro framework
Keeping it small: Getting to know the Slim micro frameworkJeremy Kendall
 
The worst Ruby codes I’ve seen in my life - RubyKaigi 2015
The worst Ruby codes I’ve seen in my life - RubyKaigi 2015The worst Ruby codes I’ve seen in my life - RubyKaigi 2015
The worst Ruby codes I’ve seen in my life - RubyKaigi 2015Fernando Hamasaki de Amorim
 
To Batch Or Not To Batch
To Batch Or Not To BatchTo Batch Or Not To Batch
To Batch Or Not To BatchLuca Mearelli
 
The Coolest Symfony Components you’ve never heard of - DrupalCon 2017
The Coolest Symfony Components you’ve never heard of - DrupalCon 2017The Coolest Symfony Components you’ve never heard of - DrupalCon 2017
The Coolest Symfony Components you’ve never heard of - DrupalCon 2017Ryan Weaver
 
Controlling The Cloud With Python
Controlling The Cloud With PythonControlling The Cloud With Python
Controlling The Cloud With PythonLuca Mearelli
 
Symfony: Your Next Microframework (SymfonyCon 2015)
Symfony: Your Next Microframework (SymfonyCon 2015)Symfony: Your Next Microframework (SymfonyCon 2015)
Symfony: Your Next Microframework (SymfonyCon 2015)Ryan Weaver
 
Symfony Guard Authentication: Fun with API Token, Social Login, JWT and more
Symfony Guard Authentication: Fun with API Token, Social Login, JWT and moreSymfony Guard Authentication: Fun with API Token, Social Login, JWT and more
Symfony Guard Authentication: Fun with API Token, Social Login, JWT and moreRyan Weaver
 
SymfonyCon Berlin 2016 - Symfony Plugin for PhpStorm - 3 years later
SymfonyCon Berlin 2016 - Symfony Plugin for PhpStorm - 3 years laterSymfonyCon Berlin 2016 - Symfony Plugin for PhpStorm - 3 years later
SymfonyCon Berlin 2016 - Symfony Plugin for PhpStorm - 3 years laterHaehnchen
 
Building Cloud Castles
Building Cloud CastlesBuilding Cloud Castles
Building Cloud CastlesBen Scofield
 
Keeping it Small: Getting to know the Slim Micro Framework
Keeping it Small: Getting to know the Slim Micro FrameworkKeeping it Small: Getting to know the Slim Micro Framework
Keeping it Small: Getting to know the Slim Micro FrameworkJeremy Kendall
 
With a Mighty Hammer
With a Mighty HammerWith a Mighty Hammer
With a Mighty HammerBen Scofield
 
Puppet for Sys Admins
Puppet for Sys AdminsPuppet for Sys Admins
Puppet for Sys AdminsPuppet
 
Keeping it small - Getting to know the Slim PHP micro framework
Keeping it small - Getting to know the Slim PHP micro frameworkKeeping it small - Getting to know the Slim PHP micro framework
Keeping it small - Getting to know the Slim PHP micro frameworkJeremy Kendall
 
Lightweight Webservices with Sinatra and RestClient
Lightweight Webservices with Sinatra and RestClientLightweight Webservices with Sinatra and RestClient
Lightweight Webservices with Sinatra and RestClientAdam Wiggins
 
Using Sinatra to Build REST APIs in Ruby
Using Sinatra to Build REST APIs in RubyUsing Sinatra to Build REST APIs in Ruby
Using Sinatra to Build REST APIs in RubyLaunchAny
 
A Little Backbone For Your App
A Little Backbone For Your AppA Little Backbone For Your App
A Little Backbone For Your AppLuca Mearelli
 
Sinatra Rack And Middleware
Sinatra Rack And MiddlewareSinatra Rack And Middleware
Sinatra Rack And MiddlewareBen Schwarz
 

Mais procurados (20)

Keeping it small: Getting to know the Slim micro framework
Keeping it small: Getting to know the Slim micro frameworkKeeping it small: Getting to know the Slim micro framework
Keeping it small: Getting to know the Slim micro framework
 
The worst Ruby codes I’ve seen in my life - RubyKaigi 2015
The worst Ruby codes I’ve seen in my life - RubyKaigi 2015The worst Ruby codes I’ve seen in my life - RubyKaigi 2015
The worst Ruby codes I’ve seen in my life - RubyKaigi 2015
 
To Batch Or Not To Batch
To Batch Or Not To BatchTo Batch Or Not To Batch
To Batch Or Not To Batch
 
The Coolest Symfony Components you’ve never heard of - DrupalCon 2017
The Coolest Symfony Components you’ve never heard of - DrupalCon 2017The Coolest Symfony Components you’ve never heard of - DrupalCon 2017
The Coolest Symfony Components you’ve never heard of - DrupalCon 2017
 
Controlling The Cloud With Python
Controlling The Cloud With PythonControlling The Cloud With Python
Controlling The Cloud With Python
 
Debugging on rails
Debugging on railsDebugging on rails
Debugging on rails
 
Symfony: Your Next Microframework (SymfonyCon 2015)
Symfony: Your Next Microframework (SymfonyCon 2015)Symfony: Your Next Microframework (SymfonyCon 2015)
Symfony: Your Next Microframework (SymfonyCon 2015)
 
Symfony Guard Authentication: Fun with API Token, Social Login, JWT and more
Symfony Guard Authentication: Fun with API Token, Social Login, JWT and moreSymfony Guard Authentication: Fun with API Token, Social Login, JWT and more
Symfony Guard Authentication: Fun with API Token, Social Login, JWT and more
 
SymfonyCon Berlin 2016 - Symfony Plugin for PhpStorm - 3 years later
SymfonyCon Berlin 2016 - Symfony Plugin for PhpStorm - 3 years laterSymfonyCon Berlin 2016 - Symfony Plugin for PhpStorm - 3 years later
SymfonyCon Berlin 2016 - Symfony Plugin for PhpStorm - 3 years later
 
Building Cloud Castles
Building Cloud CastlesBuilding Cloud Castles
Building Cloud Castles
 
Keeping it Small: Getting to know the Slim Micro Framework
Keeping it Small: Getting to know the Slim Micro FrameworkKeeping it Small: Getting to know the Slim Micro Framework
Keeping it Small: Getting to know the Slim Micro Framework
 
With a Mighty Hammer
With a Mighty HammerWith a Mighty Hammer
With a Mighty Hammer
 
Sinatra for REST services
Sinatra for REST servicesSinatra for REST services
Sinatra for REST services
 
Puppet for Sys Admins
Puppet for Sys AdminsPuppet for Sys Admins
Puppet for Sys Admins
 
Follow the White Rabbit - Message Queues with PHP
Follow the White Rabbit - Message Queues with PHPFollow the White Rabbit - Message Queues with PHP
Follow the White Rabbit - Message Queues with PHP
 
Keeping it small - Getting to know the Slim PHP micro framework
Keeping it small - Getting to know the Slim PHP micro frameworkKeeping it small - Getting to know the Slim PHP micro framework
Keeping it small - Getting to know the Slim PHP micro framework
 
Lightweight Webservices with Sinatra and RestClient
Lightweight Webservices with Sinatra and RestClientLightweight Webservices with Sinatra and RestClient
Lightweight Webservices with Sinatra and RestClient
 
Using Sinatra to Build REST APIs in Ruby
Using Sinatra to Build REST APIs in RubyUsing Sinatra to Build REST APIs in Ruby
Using Sinatra to Build REST APIs in Ruby
 
A Little Backbone For Your App
A Little Backbone For Your AppA Little Backbone For Your App
A Little Backbone For Your App
 
Sinatra Rack And Middleware
Sinatra Rack And MiddlewareSinatra Rack And Middleware
Sinatra Rack And Middleware
 

Destaque

Speed up your Symfony2 application and build awesome features with Redis
Speed up your Symfony2 application and build awesome features with RedisSpeed up your Symfony2 application and build awesome features with Redis
Speed up your Symfony2 application and build awesome features with RedisRicard Clau
 
Rationally boost your symfony2 application with caching tips and monitoring
Rationally boost your symfony2 application with caching tips and monitoringRationally boost your symfony2 application with caching tips and monitoring
Rationally boost your symfony2 application with caching tips and monitoringGiulio De Donato
 
Rich domain model with symfony 2.5 and doctrine 2.5
Rich domain model with symfony 2.5 and doctrine 2.5Rich domain model with symfony 2.5 and doctrine 2.5
Rich domain model with symfony 2.5 and doctrine 2.5Leonardo Proietti
 
Benchmark Profile and Boost your Symfony application
Benchmark Profile and Boost your Symfony applicationBenchmark Profile and Boost your Symfony application
Benchmark Profile and Boost your Symfony applicationGiulio De Donato
 
Scaling Symfony2 apps with RabbitMQ - Symfony UK Meetup
Scaling Symfony2 apps with RabbitMQ - Symfony UK MeetupScaling Symfony2 apps with RabbitMQ - Symfony UK Meetup
Scaling Symfony2 apps with RabbitMQ - Symfony UK MeetupKacper Gunia
 
Doctrine 2 - Not The Same Old Php Orm
Doctrine 2 - Not The Same Old Php OrmDoctrine 2 - Not The Same Old Php Orm
Doctrine 2 - Not The Same Old Php OrmJonathan Wage
 
Increase your performance and code quality
Increase your performance and code qualityIncrease your performance and code quality
Increase your performance and code qualityDusko Vesin
 
ORO Meetups - Doctrine Events
ORO Meetups - Doctrine EventsORO Meetups - Doctrine Events
ORO Meetups - Doctrine Eventssergeyz
 
Asynchronous processing with PHP and Symfony2. Do it simple
Asynchronous processing with PHP and Symfony2. Do it simpleAsynchronous processing with PHP and Symfony2. Do it simple
Asynchronous processing with PHP and Symfony2. Do it simpleKirill Chebunin
 
!(How to Kill MySQL Performance)
!(How to Kill MySQL Performance)!(How to Kill MySQL Performance)
!(How to Kill MySQL Performance)Vishnu Agarwal
 
You Don't Know Query - WordCamp Portland 2011
You Don't Know Query - WordCamp Portland 2011You Don't Know Query - WordCamp Portland 2011
You Don't Know Query - WordCamp Portland 2011andrewnacin
 
Symfony2 Authentication
Symfony2 AuthenticationSymfony2 Authentication
Symfony2 AuthenticationOFlorin
 
$kernel->infect(): Creating a cryptovirus for Symfony2 apps
$kernel->infect(): Creating a cryptovirus for Symfony2 apps$kernel->infect(): Creating a cryptovirus for Symfony2 apps
$kernel->infect(): Creating a cryptovirus for Symfony2 appsRaul Fraile
 
Building a Website to Scale to 100 Million Page Views Per Day and Beyond
Building a Website to Scale to 100 Million Page Views Per Day and Beyond Building a Website to Scale to 100 Million Page Views Per Day and Beyond
Building a Website to Scale to 100 Million Page Views Per Day and Beyond Trieu Nguyen
 
Making Symofny shine with Varnish - SymfonyCon Madrid 2014
Making Symofny shine with Varnish - SymfonyCon Madrid 2014Making Symofny shine with Varnish - SymfonyCon Madrid 2014
Making Symofny shine with Varnish - SymfonyCon Madrid 2014Barel Barelon
 
Living documentation mini-workshop
Living documentation mini-workshopLiving documentation mini-workshop
Living documentation mini-workshopMatthias Noback
 
Performance tips for Symfony2 & PHP
Performance tips for Symfony2 & PHPPerformance tips for Symfony2 & PHP
Performance tips for Symfony2 & PHPMax Romanovsky
 
Держим руку на пульсе проекта. Мониторинг PHP-приложений
Держим руку на пульсе проекта. Мониторинг PHP-приложенийДержим руку на пульсе проекта. Мониторинг PHP-приложений
Держим руку на пульсе проекта. Мониторинг PHP-приложенийMax Romanovsky
 

Destaque (20)

Speed up your Symfony2 application and build awesome features with Redis
Speed up your Symfony2 application and build awesome features with RedisSpeed up your Symfony2 application and build awesome features with Redis
Speed up your Symfony2 application and build awesome features with Redis
 
Rationally boost your symfony2 application with caching tips and monitoring
Rationally boost your symfony2 application with caching tips and monitoringRationally boost your symfony2 application with caching tips and monitoring
Rationally boost your symfony2 application with caching tips and monitoring
 
Rich domain model with symfony 2.5 and doctrine 2.5
Rich domain model with symfony 2.5 and doctrine 2.5Rich domain model with symfony 2.5 and doctrine 2.5
Rich domain model with symfony 2.5 and doctrine 2.5
 
Benchmark Profile and Boost your Symfony application
Benchmark Profile and Boost your Symfony applicationBenchmark Profile and Boost your Symfony application
Benchmark Profile and Boost your Symfony application
 
Scaling Symfony2 apps with RabbitMQ - Symfony UK Meetup
Scaling Symfony2 apps with RabbitMQ - Symfony UK MeetupScaling Symfony2 apps with RabbitMQ - Symfony UK Meetup
Scaling Symfony2 apps with RabbitMQ - Symfony UK Meetup
 
Doctrine 2 - Not The Same Old Php Orm
Doctrine 2 - Not The Same Old Php OrmDoctrine 2 - Not The Same Old Php Orm
Doctrine 2 - Not The Same Old Php Orm
 
Increase your performance and code quality
Increase your performance and code qualityIncrease your performance and code quality
Increase your performance and code quality
 
ORO Meetups - Doctrine Events
ORO Meetups - Doctrine EventsORO Meetups - Doctrine Events
ORO Meetups - Doctrine Events
 
Asynchronous processing with PHP and Symfony2. Do it simple
Asynchronous processing with PHP and Symfony2. Do it simpleAsynchronous processing with PHP and Symfony2. Do it simple
Asynchronous processing with PHP and Symfony2. Do it simple
 
!(How to Kill MySQL Performance)
!(How to Kill MySQL Performance)!(How to Kill MySQL Performance)
!(How to Kill MySQL Performance)
 
You Don't Know Query - WordCamp Portland 2011
You Don't Know Query - WordCamp Portland 2011You Don't Know Query - WordCamp Portland 2011
You Don't Know Query - WordCamp Portland 2011
 
Symfony2 Authentication
Symfony2 AuthenticationSymfony2 Authentication
Symfony2 Authentication
 
Doctrine for NoSQL
Doctrine for NoSQLDoctrine for NoSQL
Doctrine for NoSQL
 
$kernel->infect(): Creating a cryptovirus for Symfony2 apps
$kernel->infect(): Creating a cryptovirus for Symfony2 apps$kernel->infect(): Creating a cryptovirus for Symfony2 apps
$kernel->infect(): Creating a cryptovirus for Symfony2 apps
 
Building a Website to Scale to 100 Million Page Views Per Day and Beyond
Building a Website to Scale to 100 Million Page Views Per Day and Beyond Building a Website to Scale to 100 Million Page Views Per Day and Beyond
Building a Website to Scale to 100 Million Page Views Per Day and Beyond
 
Charting with Google
Charting with GoogleCharting with Google
Charting with Google
 
Making Symofny shine with Varnish - SymfonyCon Madrid 2014
Making Symofny shine with Varnish - SymfonyCon Madrid 2014Making Symofny shine with Varnish - SymfonyCon Madrid 2014
Making Symofny shine with Varnish - SymfonyCon Madrid 2014
 
Living documentation mini-workshop
Living documentation mini-workshopLiving documentation mini-workshop
Living documentation mini-workshop
 
Performance tips for Symfony2 & PHP
Performance tips for Symfony2 & PHPPerformance tips for Symfony2 & PHP
Performance tips for Symfony2 & PHP
 
Держим руку на пульсе проекта. Мониторинг PHP-приложений
Держим руку на пульсе проекта. Мониторинг PHP-приложенийДержим руку на пульсе проекта. Мониторинг PHP-приложений
Держим руку на пульсе проекта. Мониторинг PHP-приложений
 

Semelhante a Effective Doctrine2: Performance Tips for Symfony2 Developers

Beware the potholes on the road to serverless
Beware the potholes on the road to serverlessBeware the potholes on the road to serverless
Beware the potholes on the road to serverlessYan Cui
 
DDD on example of Symfony (SfCampUA14)
DDD on example of Symfony (SfCampUA14)DDD on example of Symfony (SfCampUA14)
DDD on example of Symfony (SfCampUA14)Oleg Zinchenko
 
Beware the potholes
Beware the potholesBeware the potholes
Beware the potholesYan Cui
 
Know your platform. 7 things every scala developer should know about jvm
Know your platform. 7 things every scala developer should know about jvmKnow your platform. 7 things every scala developer should know about jvm
Know your platform. 7 things every scala developer should know about jvmPawel Szulc
 
LinuxFest Northwest 2022 - The Evolution of a MySQL Database System
LinuxFest Northwest 2022 - The Evolution of a MySQL Database SystemLinuxFest Northwest 2022 - The Evolution of a MySQL Database System
LinuxFest Northwest 2022 - The Evolution of a MySQL Database SystemFrederic Descamps
 
theVIVI-AD-Security-Workshop_AfricaHackon2019.pdf
theVIVI-AD-Security-Workshop_AfricaHackon2019.pdftheVIVI-AD-Security-Workshop_AfricaHackon2019.pdf
theVIVI-AD-Security-Workshop_AfricaHackon2019.pdfGabriel Mathenge
 
ZF2 Modular Architecture - Taking advantage of it
ZF2 Modular Architecture - Taking advantage of itZF2 Modular Architecture - Taking advantage of it
ZF2 Modular Architecture - Taking advantage of itSteve Maraspin
 
Porting Rails Apps to High Availability Systems
Porting Rails Apps to High Availability SystemsPorting Rails Apps to High Availability Systems
Porting Rails Apps to High Availability SystemsMarcelo Pinheiro
 
Doctrine 2: Enterprise Persistence Layer for PHP
Doctrine 2: Enterprise Persistence Layer for PHPDoctrine 2: Enterprise Persistence Layer for PHP
Doctrine 2: Enterprise Persistence Layer for PHPJonathan Wage
 
Software Define your Current Storage with Opensource
Software Define your Current Storage with OpensourceSoftware Define your Current Storage with Opensource
Software Define your Current Storage with OpensourceAntonio Romeo
 
Android reverse engineering - Analyzing skype
Android reverse engineering - Analyzing skypeAndroid reverse engineering - Analyzing skype
Android reverse engineering - Analyzing skypeMário Almeida
 
Fix me if you can - DrupalCon prague
Fix me if you can - DrupalCon pragueFix me if you can - DrupalCon prague
Fix me if you can - DrupalCon praguehernanibf
 
Testing Persistent Storage Performance in Kubernetes with Sherlock
Testing Persistent Storage Performance in Kubernetes with SherlockTesting Persistent Storage Performance in Kubernetes with Sherlock
Testing Persistent Storage Performance in Kubernetes with SherlockScyllaDB
 
Review unknown code with static analysis - bredaphp
Review unknown code with static analysis - bredaphpReview unknown code with static analysis - bredaphp
Review unknown code with static analysis - bredaphpDamien Seguy
 
Replatforming Legacy Packaged Applications: Block-by-Block with Minecraft
Replatforming Legacy Packaged Applications: Block-by-Block with MinecraftReplatforming Legacy Packaged Applications: Block-by-Block with Minecraft
Replatforming Legacy Packaged Applications: Block-by-Block with MinecraftVMware Tanzu
 

Semelhante a Effective Doctrine2: Performance Tips for Symfony2 Developers (20)

Rebuilding our Foundation
Rebuilding our FoundationRebuilding our Foundation
Rebuilding our Foundation
 
Beware the potholes on the road to serverless
Beware the potholes on the road to serverlessBeware the potholes on the road to serverless
Beware the potholes on the road to serverless
 
DDD on example of Symfony (SfCampUA14)
DDD on example of Symfony (SfCampUA14)DDD on example of Symfony (SfCampUA14)
DDD on example of Symfony (SfCampUA14)
 
Beware the potholes
Beware the potholesBeware the potholes
Beware the potholes
 
Know your platform. 7 things every scala developer should know about jvm
Know your platform. 7 things every scala developer should know about jvmKnow your platform. 7 things every scala developer should know about jvm
Know your platform. 7 things every scala developer should know about jvm
 
LinuxFest Northwest 2022 - The Evolution of a MySQL Database System
LinuxFest Northwest 2022 - The Evolution of a MySQL Database SystemLinuxFest Northwest 2022 - The Evolution of a MySQL Database System
LinuxFest Northwest 2022 - The Evolution of a MySQL Database System
 
theVIVI-AD-Security-Workshop_AfricaHackon2019.pdf
theVIVI-AD-Security-Workshop_AfricaHackon2019.pdftheVIVI-AD-Security-Workshop_AfricaHackon2019.pdf
theVIVI-AD-Security-Workshop_AfricaHackon2019.pdf
 
ZF2 Modular Architecture - Taking advantage of it
ZF2 Modular Architecture - Taking advantage of itZF2 Modular Architecture - Taking advantage of it
ZF2 Modular Architecture - Taking advantage of it
 
20180811 coscup
20180811 coscup20180811 coscup
20180811 coscup
 
Porting Rails Apps to High Availability Systems
Porting Rails Apps to High Availability SystemsPorting Rails Apps to High Availability Systems
Porting Rails Apps to High Availability Systems
 
Ruby For Startups
Ruby For StartupsRuby For Startups
Ruby For Startups
 
Jax London 2013
Jax London 2013Jax London 2013
Jax London 2013
 
Doctrine 2: Enterprise Persistence Layer for PHP
Doctrine 2: Enterprise Persistence Layer for PHPDoctrine 2: Enterprise Persistence Layer for PHP
Doctrine 2: Enterprise Persistence Layer for PHP
 
Software Define your Current Storage with Opensource
Software Define your Current Storage with OpensourceSoftware Define your Current Storage with Opensource
Software Define your Current Storage with Opensource
 
Android reverse engineering - Analyzing skype
Android reverse engineering - Analyzing skypeAndroid reverse engineering - Analyzing skype
Android reverse engineering - Analyzing skype
 
Fix me if you can - DrupalCon prague
Fix me if you can - DrupalCon pragueFix me if you can - DrupalCon prague
Fix me if you can - DrupalCon prague
 
Testing Persistent Storage Performance in Kubernetes with Sherlock
Testing Persistent Storage Performance in Kubernetes with SherlockTesting Persistent Storage Performance in Kubernetes with Sherlock
Testing Persistent Storage Performance in Kubernetes with Sherlock
 
Review unknown code with static analysis - bredaphp
Review unknown code with static analysis - bredaphpReview unknown code with static analysis - bredaphp
Review unknown code with static analysis - bredaphp
 
Replatforming Legacy Packaged Applications: Block-by-Block with Minecraft
Replatforming Legacy Packaged Applications: Block-by-Block with MinecraftReplatforming Legacy Packaged Applications: Block-by-Block with Minecraft
Replatforming Legacy Packaged Applications: Block-by-Block with Minecraft
 
TSRT Crashes
TSRT CrashesTSRT Crashes
TSRT Crashes
 

Último

Understanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitectureUnderstanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitecturePixlogix Infotech
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slidevu2urc
 
Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Paola De la Torre
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationMichael W. Hawkins
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)Gabriella Davis
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonAnna Loughnan Colquhoun
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxMalak Abu Hammad
 
My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationRidwan Fadjar
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonetsnaman860154
 
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024BookNet Canada
 
Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...Alan Dix
 
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | DelhiFULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhisoniya singh
 
Enhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for PartnersEnhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for PartnersThousandEyes
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking MenDelhi Call girls
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationRadu Cotescu
 
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure serviceWhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure servicePooja Nehwal
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking MenDelhi Call girls
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking MenDelhi Call girls
 
Maximizing Board Effectiveness 2024 Webinar.pptx
Maximizing Board Effectiveness 2024 Webinar.pptxMaximizing Board Effectiveness 2024 Webinar.pptx
Maximizing Board Effectiveness 2024 Webinar.pptxOnBoard
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptxHampshireHUG
 

Último (20)

Understanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitectureUnderstanding the Laravel MVC Architecture
Understanding the Laravel MVC Architecture
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
 
Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day Presentation
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt Robison
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptx
 
My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 Presentation
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonets
 
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
 
Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...
 
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | DelhiFULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
 
Enhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for PartnersEnhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for Partners
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organization
 
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure serviceWhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
 
Maximizing Board Effectiveness 2024 Webinar.pptx
Maximizing Board Effectiveness 2024 Webinar.pptxMaximizing Board Effectiveness 2024 Webinar.pptx
Maximizing Board Effectiveness 2024 Webinar.pptx
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
 

Effective Doctrine2: Performance Tips for Symfony2 Developers

  • 1. Effective Doctrine2 Performance Tips for Symfony2 Developers Wrocław Symfony Group #2 April 24th, 2014
  • 2. Effective Doctrine2: Performance Tips for Symfony2 Developers marcin.chwedziak Who am I?
  • 3. Effective Doctrine2: Performance Tips for Symfony2 Developers marcin.chwedziak Symfony2 ContributorSilex Contributor Symfony2 Developer Angular.jsDeveloper AgileEnthusiast „No worries, I will handle this” AppreciatedContractor Marcin Chwedziak github.com/tiraeth lnkd.in/dp6sPzc Software Engineer at Spork Labs LLP (Salt Lake City, UT)
  • 4. Effective Doctrine2: Performance Tips for Symfony2 Developers marcin.chwedziak What is this talk about?
  • 5. Effective Doctrine2: Performance Tips for Symfony2 Developers marcin.chwedziak plus things that can go wrong while working with Symfony2 107 queries executed in 17.25 seconds
  • 6. Effective Doctrine2: Performance Tips for Symfony2 Developers marcin.chwedziak While working with databases, the most important strategy is to avoid querying a database.
  • 7. Effective Doctrine2: Performance Tips for Symfony2 Developers marcin.chwedziak Rule #1: Caching
  • 8. Effective Doctrine2: Performance Tips for Symfony2 Developers marcin.chwedziak If you must query a database, be wise and do it smarter.
  • 9. Effective Doctrine2: Performance Tips for Symfony2 Developers marcin.chwedziak Rule #2: Code Optimization
  • 10. Effective Doctrine2: Performance Tips for Symfony2 Developers marcin.chwedziak Smart behaviour also means to be explicit in actions.
  • 11. Effective Doctrine2: Performance Tips for Symfony2 Developers marcin.chwedziak Rule #3: Transaction Demarcation
  • 12. Effective Doctrine2: Performance Tips for Symfony2 Developers marcin.chwedziak Caching w/ Doctrine2
  • 13. Effective Doctrine2: Performance Tips for Symfony2 Developers marcin.chwedziak Metadata What can be effectively cached? Query Result
  • 14. Effective Doctrine2: Performance Tips for Symfony2 Developers marcin.chwedziak Parsing model metadata from different sources with each request can have a serious impact on your application’s performance. It is a good practice to cache it.
  • 15. Effective Doctrine2: Performance Tips for Symfony2 Developers marcin.chwedziak Each time you write a DQL query or use the QueryBuilder to create one, Doctrine has to transform that query to SQL. This is an unnecessary waste of available resources.
  • 16. Effective Doctrine2: Performance Tips for Symfony2 Developers marcin.chwedziak Usually, there is no special reason to hit a database for rarely modified data. Configure Result Cache strategy to make sure that your database is not swamped with such queries.
  • 17. Effective Doctrine2: Performance Tips for Symfony2 Developers marcin.chwedziak Be aware! Make sure you properly create your queries.
  • 18. Effective Doctrine2: Performance Tips for Symfony2 Developers marcin.chwedziak # Fetch expired subscriptions (non-cachable) SELECT s FROM ASBillingBundle:Subscription s WHERE s.validTo < ? [1397855248] ! # Fetch expired subscriptions (cachable) SELECT s FROM ASBillingBundle:Subscription s WHERE s.validTo < CURRENT_TIMESTAMP() You can cache both DQL and Native SQL queries.
  • 19. Effective Doctrine2: Performance Tips for Symfony2 Developers marcin.chwedziak How to cache metadata in Symfony2?
  • 20. Effective Doctrine2: Performance Tips for Symfony2 Developers marcin.chwedziak app/config/config_prod.yml doctrine: orm: # ... metadata_cache_driver: apc # ...
  • 21. Effective Doctrine2: Performance Tips for Symfony2 Developers marcin.chwedziak Can I implement custom caching service?
  • 22. Effective Doctrine2: Performance Tips for Symfony2 Developers marcin.chwedziak app/config/config_prod.yml doctrine: orm: # ... metadata_cache_driver: type: service id: as.doctrine.cache.couchbase # ...
  • 23. Effective Doctrine2: Performance Tips for Symfony2 Developers marcin.chwedziak src/AS/CoreBundle/Doctrine/Cache/CouchbaseCache.php <?php ! namespace AS/CoreBundle/Doctrine/Cache; ! use DoctrineCommonCacheCacheProvider; ! class CouchbaseCache extends CacheProvider
 { // doFetch($id) // doContains($id) // doSave($id, $data, $liteTime = 0) // doDelete($id) // doFlush() // doGetStats() }
  • 24. Effective Doctrine2: Performance Tips for Symfony2 Developers marcin.chwedziak How to cache queries in Symfony2?
  • 25. Effective Doctrine2: Performance Tips for Symfony2 Developers marcin.chwedziak app/config/config_prod.yml doctrine: orm: # ... query_cache_driver: apc # ...
  • 26. Effective Doctrine2: Performance Tips for Symfony2 Developers marcin.chwedziak How to cache query results in Symfony2?
  • 27. Effective Doctrine2: Performance Tips for Symfony2 Developers marcin.chwedziak app/config/config_prod.yml doctrine: orm: # ... result_cache_driver: apc # ...
  • 28. Effective Doctrine2: Performance Tips for Symfony2 Developers marcin.chwedziak Setting caching driver for Query Result Cache is not sufficient for enabling the strategy. You need to explicitly enable it for each and every query you’re interested in.
  • 29. Effective Doctrine2: Performance Tips for Symfony2 Developers marcin.chwedziak <?php ! // ... ! $query = $em->createQuery($dql); $query->useResultCache(true); ! // …
  • 30. Effective Doctrine2: Performance Tips for Symfony2 Developers marcin.chwedziak With great power comes great responsibility. Voltaire (1694-1778)
  • 31. Effective Doctrine2: Performance Tips for Symfony2 Developers marcin.chwedziak Be aware that high traffic websites can generate races while accessing cached data. This situation is called cache slam. When implementing own cache driver, please refer to your backend’s documentation regarding races avoidance.
  • 32. Effective Doctrine2: Performance Tips for Symfony2 Developers marcin.chwedziak If anything goes wrong, you can manually clear the cache without restarting/flushing the storage. php app/console doctrine:cache:clear-metadata php app/console doctrine:cache:clear-query php app/console doctrine:cache:clear-result
  • 33. Effective Doctrine2: Performance Tips for Symfony2 Developers marcin.chwedziak Optimization Guidelines
  • 34. Effective Doctrine2: Performance Tips for Symfony2 Developers marcin.chwedziak You can begin your journey with code optimization while using Doctrine2 with properly set up domain models. Please be aware that the following guidelines are for use with Doctrine2, not necessarily with database design in general.
  • 35. Effective Doctrine2: Performance Tips for Symfony2 Developers marcin.chwedziak Step 1: Avoid bidirectional associations
  • 36. Effective Doctrine2: Performance Tips for Symfony2 Developers marcin.chwedziak If you really need bidirectional associations, try to use lazy fetching strategy, but in most cases bidirectional relations are not necessary and should be avoided.
  • 37. Effective Doctrine2: Performance Tips for Symfony2 Developers marcin.chwedziak Be aware that lazy fetching strategy creates dynamic proxy objects (class is generated on the fly). Fortunately, Symfony2 handles proxy generation with cache warmup task.
  • 38. Effective Doctrine2: Performance Tips for Symfony2 Developers marcin.chwedziak For aggregations (with Collections) you can use EXTRA LAZY strategy which will not load the whole collection on first access, as it is done in LAZY strategy.
  • 39. Effective Doctrine2: Performance Tips for Symfony2 Developers marcin.chwedziak Dropping such relations does not mean that you can’t use JOIN with your DQL / Native SQL queries.
  • 40. Effective Doctrine2: Performance Tips for Symfony2 Developers marcin.chwedziak <?php ! namespace ASBillingBundleEntity; ! class Subscription { /** * @ORMManyToOne(targetEntity="User") * @ORMJoinColumn(name="user_id", referencedColumnName="id") */ protected $user; } ! ! ! class User { // ... }
  • 41. Effective Doctrine2: Performance Tips for Symfony2 Developers marcin.chwedziak SELECT u FROM ASBillingBundle:User u JOIN ASBillingBundle:Subscription s WITH s.user = u WHERE s.validTo <= CURRENT_DATE()
  • 42. Effective Doctrine2: Performance Tips for Symfony2 Developers marcin.chwedziak Step 2: Avoid unnecessary cascades
  • 43. Effective Doctrine2: Performance Tips for Symfony2 Developers marcin.chwedziak 1. Do not configure cascade operations on every association you have in your domain. 2. Unless required (e.g. additional file removal), use DBMS cascades instead of ORM ones.
  • 44. Effective Doctrine2: Performance Tips for Symfony2 Developers marcin.chwedziak Remember that you do not setup ORM cascades on target entites but on the triggering ones. Opposite to DBMS configuration.
  • 45. Effective Doctrine2: Performance Tips for Symfony2 Developers marcin.chwedziak <?php ! namespace ASBillingBundleEntity; ! class Subscription { /** * @ORMOneToOne(targetEntity="User", cascade={"remove"}) * @ORMJoinColumn(name="user_id", referencedColumnName="id") */ protected $user; } This is wrong:
  • 46. Effective Doctrine2: Performance Tips for Symfony2 Developers marcin.chwedziak <?php ! namespace ASBillingBundleEntity; ! class Subscription { /** * @ORMManyToOne(targetEntity="User") * @ORMJoinColumn( * name="user_id", * referencedColumnName="id", * onDelete="CASCADE" * ) */ protected $user; } This is correct:
  • 47. Effective Doctrine2: Performance Tips for Symfony2 Developers marcin.chwedziak Step 3: Avoid lifecycle events abuse
  • 48. Effective Doctrine2: Performance Tips for Symfony2 Developers marcin.chwedziak Be smart about listening to lifecycle events like persist, update, or remove. Know the difference between Listener and Subscriber. Do not identify Doctrine2 event subscribers with Symfony2 subscribers, which are more dynamic!
  • 49. Effective Doctrine2: Performance Tips for Symfony2 Developers marcin.chwedziak Avoid requiring EntityManager in your event listeners (it will just not work).
  • 50. Effective Doctrine2: Performance Tips for Symfony2 Developers marcin.chwedziak <?php ! namespace ASBillingBundleListener; ! use SymfonyBridgeDoctrineRegistryInterface; ! abstract class LifecycleListener { protected $doctrine; protected $manager; ! public function __construct( RegistryInterface $doctrine, $manager = 'default' ) { $this->doctrine = $doctrine; $this->manager = $manager; } ! protected function getEntityManager() { return $this->doctrine->getEntityManager($this->manager); } }
  • 51. Effective Doctrine2: Performance Tips for Symfony2 Developers marcin.chwedziak Step 4: Load from database what you need
  • 52. Effective Doctrine2: Performance Tips for Symfony2 Developers marcin.chwedziak Fetch Modes Return only data you are in need of. Hydration Modes Partial Objects
  • 53. Effective Doctrine2: Performance Tips for Symfony2 Developers marcin.chwedziak When dealing with one-to-one and many-to-one relations, you can switch between EAGER and LAZY fetching modes right in your Query object. <?php ! $query = $em->createQuery( "SELECT s FROM ASBillingBundle:Subscription s" ) ->setFetchMode( "ASBillingBundle:Subscription", "user", DoctrineORMMappingClassMetadata::FETCH_EAGER );
  • 54. Effective Doctrine2: Performance Tips for Symfony2 Developers marcin.chwedziak If not necessary, do not fetch a whole object (with relations) to just get its „validTo” field value. <?php ! $expirationDate = $em->createQuery( "SELECT s.validTo " . "FROM ASBillingBundle:Subscription s " . "WHERE s.user = ?1" ) ->setParameter(1, $user) ->getSingleScalarResult();
  • 55. Effective Doctrine2: Performance Tips for Symfony2 Developers marcin.chwedziak Unless you can deal with scalar values or arrays, you may need to wrap data in your model’s class. Use Partial Objects for this purpose. <?php ! $reference = $em->createQuery( "SELECT PARTIAL s.{plan,validTo} " . "FROM ASBillingBundle:Subscription s " . "WHERE s.id = ?1" )->setParameter(1, $id)->getResult(); ! $reference->getPartialReference("ASBillingBundle:Subscription", $id);
  • 56. Effective Doctrine2: Performance Tips for Symfony2 Developers marcin.chwedziak Step 4: Load from database when you need
  • 57. Effective Doctrine2: Performance Tips for Symfony2 Developers marcin.chwedziak If you have to process data for large result sets, think about using DQL UPDATE/DELETE queries or Iterable Result. When using Iterable Result always remember to detach all existing and not required anymore objects from Doctrine!
  • 58. Effective Doctrine2: Performance Tips for Symfony2 Developers marcin.chwedziak <?php ! $batch = 50; $i = 0; ! $iterableResult = $em->createQuery( "SELECT s FROM ASBillingBundle:Subscription s" )->iterate(); ! foreach ($iterableResult as $row) { $subscription = $row[0]; $subscription->renew(); if (($i % $batch) === 0) { $em->flush(); // Execute queued updates $em->clear(); // Detach objects and GC them } ++$i; } ! $em->flush(); // Execute remainig updates $em->clear(); // Detach remaining objects and GC them
  • 59. Effective Doctrine2: Performance Tips for Symfony2 Developers marcin.chwedziak <?php ! $iterableResult = $em->createQuery( "SELECT s FROM ASBillingBundle:Subscription s " . "WHERE s.validTo = CURRENT_DATE() AND s.trialing = TRUE" )->iterate(); ! foreach ($iterableResult as $row) { $mailer->notifyTrialExpiration($row[0]); $em->detach($row[0]); // Detach and GC immediately }
  • 60. Effective Doctrine2: Performance Tips for Symfony2 Developers marcin.chwedziak Transaction Demarcation
  • 61. Effective Doctrine2: Performance Tips for Symfony2 Developers marcin.chwedziak Proper transaction boundary definition can have positive impact on your application’s performance. Doctrine2 takes care of proper implicit demarcation for UnitOfWork–handled objects and queue all operations until EntityManager#flush() is invoked.
  • 62. Effective Doctrine2: Performance Tips for Symfony2 Developers marcin.chwedziak However, Doctrine2 encourages developers to take over and control transaction demarcation tasks themselves. Please remember to flush the EntityManager prior to transaction commit. In case of any exceptions, always close the EntityManager.
  • 63. Effective Doctrine2: Performance Tips for Symfony2 Developers marcin.chwedziak <?php ! $em->getConnection()->beginTransaction(); ! try { $user = new User; $subscription = new Subscription; $subscription->setUser($user); ! // ... do some work ! $em->persist($user); $em->persist($subscription); $em->flush(); $em->getConnection()->commit(); } catch (Exception $e) { $em->getConnection()->rollback(); $em->close(); ! // ... do something about the exception }
  • 64. Effective Doctrine2: Performance Tips for Symfony2 Developers marcin.chwedziak <?php ! $em->transactional(function($em) { $user = new User; $subscription = new Subscription; $subscription->setUser($user); ! // ... do some work ! $em->persist($user); $em->persist($subscription); }); Using EntityManager#transactional() will automatically flush the manager prior to commit.
  • 65. Effective Doctrine2: Performance Tips for Symfony2 Developers marcin.chwedziak <?php ! $em->getConnection()->transactional(function($em) { $user = new User; $subscription = new Subscription; $subscription->setUser($user); ! // ... do some work ! $em->persist($user); $em->persist($subscription); $em->flush(); }); Warning! This will not close EntityManager on exception.
  • 66. Thank you! Wrocław Symfony Group #2 April 24th, 2014