From 255127081a368dd1c8d37a833979a5fab5328df6 Mon Sep 17 00:00:00 2001 From: Victor Berchet Date: Fri, 13 Apr 2012 17:10:57 +0200 Subject: [PATCH 1/2] [Profiler] Minimize the number of Profile writes squash squash --- ...ContainerAwareTraceableEventDispatcher.php | 49 ++++++++++++++----- .../EventListener/ProfilerListener.php | 34 +++++++++++-- 2 files changed, 65 insertions(+), 18 deletions(-) diff --git a/src/Symfony/Component/HttpKernel/Debug/ContainerAwareTraceableEventDispatcher.php b/src/Symfony/Component/HttpKernel/Debug/ContainerAwareTraceableEventDispatcher.php index e9b1d8fe657ed..66ea7b63528bc 100644 --- a/src/Symfony/Component/HttpKernel/Debug/ContainerAwareTraceableEventDispatcher.php +++ b/src/Symfony/Component/HttpKernel/Debug/ContainerAwareTraceableEventDispatcher.php @@ -13,7 +13,9 @@ use Symfony\Component\HttpKernel\Debug\Stopwatch; use Symfony\Component\HttpKernel\Log\LoggerInterface; +use Symfony\Component\HttpKernel\Profiler\Profile; use Symfony\Component\HttpKernel\Profiler\Profiler; +use Symfony\Component\HttpKernel\HttpKernelInterface; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\EventDispatcher\Event; use Symfony\Component\EventDispatcher\ContainerAwareEventDispatcher; @@ -30,6 +32,7 @@ class ContainerAwareTraceableEventDispatcher extends ContainerAwareEventDispatch private $called; private $stopwatch; private $priorities; + private $profiler; /** * Constructor. @@ -83,11 +86,18 @@ public function dispatch($eventName, Event $event = null) case 'kernel.response': $token = $event->getResponse()->headers->get('X-Debug-Token'); $this->stopwatch->stopSection($token); - $this->updateProfile($token); + if (HttpKernelInterface::MASTER_REQUEST === $event->getRequestType()) { + // The profiles can only be updated once they have been created + // that is after the 'kernel.response' event of the main request + $this->updateProfiles($token, true); + } break; case 'kernel.terminate': $this->stopwatch->stopSection($token); - $this->updateProfile($token); + // The children profiles have been updated by the previous 'kernel.response' + // event. Only the root profile need to be updated with the 'kernel.terminate' + // timing informations. + $this->updateProfiles($token, false); break; } @@ -255,28 +265,41 @@ private function getListenerInfo($listener, $eventName) } /** - * Updates the profile data. + * Updates the stopwatch data in the profile hierarchy. * - * @param string $token Profile token + * @param string $token Profile token + * @param Boolean $updateChildren Whether to update the children altogether */ - private function updateProfile($token) + private function updateProfiles($token, $updateChildren) { if (!$this->getContainer()->has('profiler')) { return; } - $profiler = $this->getContainer()->get('profiler'); - if (!$profile = $profiler->loadProfile($token)) { + $this->profiler = $this->getContainer()->get('profiler'); + + if (!$profile = $this->profiler->loadProfile($token)) { return; } - $profile->getCollector('time')->setEvents($this->stopwatch->getSectionEvents($token)); - $profiler->saveProfile($profile); + $this->saveStopwatchInfoInProfile($profile, $updateChildren); + } - // children - foreach ($profile->getChildren() as $child) { - $child->getCollector('time')->setEvents($this->stopwatch->getSectionEvents($child->getToken())); - $profiler->saveProfile($child); + /** + * Update the profiles with the timing info and saves them. + * + * @param Profile $profile The root profile + * @param Boolean $updateChildren Whether to update the children altogether + */ + private function saveStopwatchInfoInProfile(Profile $profile, $updateChildren) + { + $profile->getCollector('time')->setEvents($this->stopwatch->getSectionEvents($profile->getToken())); + $this->profiler->saveProfile($profile); + + if ($updateChildren) { + foreach ($profile->getChildren() as $child) { + $this->saveStopwatchInfoInProfile($child, true); + } } } diff --git a/src/Symfony/Component/HttpKernel/EventListener/ProfilerListener.php b/src/Symfony/Component/HttpKernel/EventListener/ProfilerListener.php index dbbb441889e7d..83ee82a8d42c9 100644 --- a/src/Symfony/Component/HttpKernel/EventListener/ProfilerListener.php +++ b/src/Symfony/Component/HttpKernel/EventListener/ProfilerListener.php @@ -16,6 +16,7 @@ use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent; use Symfony\Component\HttpKernel\Event\FilterResponseEvent; use Symfony\Component\HttpKernel\KernelEvents; +use Symfony\Component\HttpKernel\Profiler\Profile; use Symfony\Component\HttpKernel\Profiler\Profiler; use Symfony\Component\HttpFoundation\RequestMatcherInterface; use Symfony\Component\EventDispatcher\EventSubscriberInterface; @@ -34,6 +35,7 @@ class ProfilerListener implements EventSubscriberInterface protected $exception; protected $children; protected $requests; + protected $profiles; /** * Constructor. @@ -50,6 +52,7 @@ public function __construct(Profiler $profiler, RequestMatcherInterface $matcher $this->onlyException = (Boolean) $onlyException; $this->onlyMasterRequests = (Boolean) $onlyMasterRequests; $this->children = new \SplObjectStorage(); + $this->profiles = array(); } /** @@ -99,6 +102,16 @@ public function onKernelResponse(FilterResponseEvent $event) return; } + $this->profiles[] = $profile; + + if (null !== $exception) { + foreach ($this->profiles as $profile) { + $this->profiler->saveProfile($profile); + } + + return; + } + // keep the profile as the child of its parent if (!$master) { array_pop($this->requests); @@ -109,17 +122,16 @@ public function onKernelResponse(FilterResponseEvent $event) $this->children[$parent] = $profiles; } - // store the profile and its children if (isset($this->children[$request])) { foreach ($this->children[$request] as $child) { - $child->setParent($profile); $profile->addChild($child); - $this->profiler->saveProfile($child); } $this->children[$request] = array(); } - $this->profiler->saveProfile($profile); + if ($master) { + $this->saveProfiles($profile); + } } static public function getSubscribedEvents() @@ -128,9 +140,21 @@ static public function getSubscribedEvents() // kernel.request must be registered as early as possible to not break // when an exception is thrown in any other kernel.request listener KernelEvents::REQUEST => array('onKernelRequest', 1024), - KernelEvents::RESPONSE => array('onKernelResponse', -100), KernelEvents::EXCEPTION => 'onKernelException', ); } + + /** + * Saves the profile hierarchy. + * + * @param Profile $profile The root profile + */ + private function saveProfiles(Profile $profile) + { + $this->profiler->saveProfile($profile); + foreach ($profile->getChildren() as $profile) { + $this->saveProfiles($profile); + } + } } From b611db8e4105cbfed6a8c95b06b981e7462ead3b Mon Sep 17 00:00:00 2001 From: Victor Berchet Date: Fri, 13 Apr 2012 18:40:08 +0200 Subject: [PATCH 2/2] [Profiler] Sub requests are not Main requests --- .../WebProfilerBundle/Resources/views/Collector/time.html.twig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/time.html.twig b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/time.html.twig index e58ffae11caf6..39d341f28c2b2 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/time.html.twig +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/time.html.twig @@ -63,7 +63,7 @@

- Main Request + {{ profile.parent ? "Request" : "Main Request" }} - {{ collector.events.__section__.totaltime }} ms {% if profile.parent %}