WEBVTT

NOTE Created by CaptionSync from Automatic Sync Technologies www.automaticsync.com

00:00:00.686 --> 00:00:01.996 align:middle
I want to show a...

00:00:02.216 --> 00:00:04.306 align:middle
more subtle performance problem.

00:00:04.706 --> 00:00:08.476 align:middle
To even see it, we need to go
back to the prod environment.

00:00:10.006 --> 00:00:19.446 align:middle
Make sure to run cache:clear: cache:warmup:
And also: composer dump-autoload --

00:00:19.446 --> 00:00:26.426 align:middle
optimize Let's create a fresh
profile of the homepage.

00:00:28.316 --> 00:00:31.356 align:middle
I'll call this one: [Recording] Homepage prod.

00:00:33.036 --> 00:00:34.706 align:middle
Click to view the timeline:

00:00:34.706 --> 00:00:41.166 align:middle
http://bit.ly/sf-bf-instantiation
Overall, this request is pretty fast.

00:00:41.166 --> 00:00:42.066 align:middle
Click into the "Memory" dimension.

00:00:43.336 --> 00:00:46.586 align:middle
The biggest call is
Composer\Autoload\includeFile:

00:00:46.996 --> 00:00:51.116 align:middle
that's literally Composer
including files that we need...

00:00:51.236 --> 00:00:54.726 align:middle
not a lot of memory optimization
we can do about that.

00:00:55.756 --> 00:01:00.566 align:middle
But, if we look closer, the memory
dimension reveals something else.

00:01:01.036 --> 00:01:04.226 align:middle
See this "Container" thing - the
2nd item on the function list?

00:01:04.966 --> 00:01:08.776 align:middle
This is related to Symfony's
container, which is responsible

00:01:08.776 --> 00:01:11.576 align:middle
for instantiating all of our objects.

00:01:12.276 --> 00:01:17.146 align:middle
This specific function is interesting:
it's highlighting a section of a file

00:01:17.146 --> 00:01:18.856 align:middle
that lives in our cache directory.

00:01:19.536 --> 00:01:24.026 align:middle
If you looked in that file, you would see
that this part of the code is responsible

00:01:24.026 --> 00:01:28.516 align:middle
for including some of the
main files that our app needs.

00:01:29.196 --> 00:01:32.236 align:middle
It's basically another version of the top node:

00:01:32.596 --> 00:01:35.906 align:middle
it's code that includes files
for classes we're using.

00:01:37.056 --> 00:01:40.346 align:middle
Ok, so the first few aren't
really that interesting.

00:01:40.896 --> 00:01:45.186 align:middle
Things get much more intriguing
down on the 4th function call:

00:01:45.826 --> 00:01:52.916 align:middle
some Container{BlahBlah}
/getDoctrine_Orm_DefaultEntityManagerService.php

00:01:53.006 --> 00:01:53.976 align:middle
call.

00:01:54.646 --> 00:01:55.956 align:middle
What is this?

00:01:56.526 --> 00:02:02.546 align:middle
Well, the details of how this is organized
are specific to Symfony: but this is evidence

00:02:02.546 --> 00:02:08.896 align:middle
of something that every app does: this
is showing the amount of resources used

00:02:09.216 --> 00:02:12.906 align:middle
to instantiate Doctrine's EntityManager object.

00:02:13.876 --> 00:02:18.876 align:middle
I know, we don't often think about how
much time or how much memory it takes

00:02:18.876 --> 00:02:23.856 align:middle
to instantiate an object, but
it can sometimes be a problem.

00:02:24.556 --> 00:02:29.356 align:middle
The next function call is for the
instantiation of Doctrine's Connection service.

00:02:29.976 --> 00:02:31.416 align:middle
Go down a little bit...

00:02:31.416 --> 00:02:33.406 align:middle
I'm looking for something specific...

00:02:35.396 --> 00:02:38.946 align:middle
here it is: getLoginFormAuthenticatorService.

00:02:39.506 --> 00:02:45.366 align:middle
This is responsible for instantiating a
LoginFormAuthenticator object in our app.

00:02:46.046 --> 00:02:52.106 align:middle
It's not a particularly problematic
function though: it's 10th on the list...

00:02:52.106 --> 00:02:57.346 align:middle
only takes 2.56 milliseconds
and uses about 500 kilobytes.

00:02:59.236 --> 00:03:05.356 align:middle
Let's check out the class:
src/Security/LoginFormAuthenticator.php.

00:03:05.356 --> 00:03:08.496 align:middle
As its name suggests, this is responsible

00:03:08.496 --> 00:03:12.326 align:middle
for authenticating the user
when they submit the login form.

00:03:13.146 --> 00:03:15.686 align:middle
But, there's something special about this class.

00:03:16.206 --> 00:03:19.256 align:middle
Due to the way the Symfony
security system works,

00:03:19.566 --> 00:03:23.436 align:middle
Symfony instantiates this
object on every request.

00:03:24.106 --> 00:03:30.126 align:middle
It does that so it can then call supports()
to figure out if this service should be

00:03:30.286 --> 00:03:32.676 align:middle
"activated" on this request or not.

00:03:32.736 --> 00:03:40.966 align:middle
For this class, it only needs to its work when
the URL is /login and this is a POST request.

00:03:41.666 --> 00:03:45.056 align:middle
In every other situation,
supports() returns false

00:03:45.436 --> 00:03:48.506 align:middle
and no other methods are called on this class.

00:03:49.296 --> 00:03:51.006 align:middle
So let's think about this.

00:03:52.456 --> 00:03:57.296 align:middle
Instantiating this class takes about
3 milliseconds and 500 kilobytes...

00:03:57.376 --> 00:03:59.556 align:middle
which is not a ton...

00:04:00.146 --> 00:04:05.416 align:middle
but since all it needs to do for most
requests is check the current URL...

00:04:05.646 --> 00:04:06.566 align:middle
then exit...

00:04:06.806 --> 00:04:08.646 align:middle
that is kind of heavy.

00:04:09.536 --> 00:04:14.226 align:middle
The question is: why does it take
so many resources to instantiate?

00:04:15.156 --> 00:04:20.666 align:middle
Well, 500 kilobytes is not a ton, but
this is - according to Blackfire -

00:04:21.036 --> 00:04:25.736 align:middle
one of the most expensive objects
that is created on this request.

00:04:26.096 --> 00:04:28.586 align:middle
Why? Check out the constructor.

00:04:29.176 --> 00:04:30.786 align:middle
In order to instantiate this class,

00:04:31.046 --> 00:04:34.776 align:middle
Symfony needs to make sure the
EntityManager is instantiated...

00:04:35.046 --> 00:04:36.786 align:middle
and the UrlGenerator..

00:04:37.486 --> 00:04:39.596 align:middle
and the CsrfTokenManager...

00:04:39.856 --> 00:04:41.986 align:middle
and the UserPasswordEncoder.

00:04:42.636 --> 00:04:46.346 align:middle
If any of these services
have their own dependencies,

00:04:46.696 --> 00:04:49.926 align:middle
even more objects may need to be instantiated.

00:04:50.616 --> 00:04:55.086 align:middle
In rare situations, creating a service
can be a huge performance problem.

00:04:55.746 --> 00:04:59.086 align:middle
In the case of the EntityManager
and the UrlGenerator...

00:04:59.296 --> 00:05:05.506 align:middle
those are pretty core objects that would
probably be needed and thus instantiated

00:05:05.706 --> 00:05:08.416 align:middle
by something on this request anyways.

00:05:09.366 --> 00:05:15.366 align:middle
But CsrfTokenManager and
UserPasswordEncoder are not normally needed.

00:05:15.946 --> 00:05:19.416 align:middle
In other words, we're forcing
Symfony to instantiate both

00:05:19.416 --> 00:05:22.146 align:middle
of those services on every request...

00:05:22.556 --> 00:05:27.036 align:middle
even though we only need them when
the user is submitting the login form.

00:05:28.186 --> 00:05:34.366 align:middle
This is a classic situation where you have an
object that is instantiated on every request...

00:05:34.776 --> 00:05:38.836 align:middle
but only needs to do real work in rare cases.

00:05:39.596 --> 00:05:43.446 align:middle
Certain event subscribers - like
our AgreeToTermsSubscriber -

00:05:43.796 --> 00:05:48.556 align:middle
Symfony security voters &amp; Twig extensions
are other examples from Symfony.

00:05:49.076 --> 00:05:51.776 align:middle
These services might be quick to instantiate...

00:05:51.776 --> 00:05:53.056 align:middle
so no problem!

00:05:53.536 --> 00:05:56.146 align:middle
But they also might be expensive.

00:05:56.926 --> 00:06:01.556 align:middle
So... how could we make it quicker to
instantiate LoginFormAuthenticator?

00:06:02.066 --> 00:06:05.076 align:middle
In Symfony, with a service subscriber.

