@@ -8,14 +8,24 @@ Symfony is fast, right out of the box. However, you can make it faster if you
8
8
optimize your servers and your applications as explained in the following
9
9
performance checklists.
10
10
11
- Symfony Application Checklist
12
- -----------------------------
11
+ Performance Checklists
12
+ ----------------------
13
13
14
- These are the code and configuration changes that you can make in your Symfony
15
- application to improve its performance:
14
+ Use these checklists to verify that your application and server are configured
15
+ for maximum performance:
16
16
17
- #. :ref: `Install APCu Polyfill if your server uses APC <performance-install-apcu-polyfill >`
18
- #. :ref: `Dump the service container into a single file <performance-service-container-single-file >`
17
+ * **Symfony Application Checklist **:
18
+
19
+ #. :ref: `Install APCu Polyfill if your server uses APC <performance-install-apcu-polyfill >`
20
+
21
+ * **Production Server Checklist **:
22
+
23
+ #. :ref: `Dump the service container into a single file <performance-service-container-single-file >`
24
+ #. :ref: `Use the OPcache byte code cache <performance-use-opcache >`
25
+ #. :ref: `Configure OPcache for maximum performance <performance-configure-opcache >`
26
+ #. :ref: `Don't check PHP files timestamps <performance-dont-check-timestamps >`
27
+ #. :ref: `Configure the PHP realpath Cache <performance-configure-realpath-cache >`
28
+ #. :ref: `Optimize Composer Autoloader <performance-optimize-composer-autoloader >`
19
29
20
30
.. _performance-install-apcu-polyfill :
21
31
@@ -72,19 +82,6 @@ container into a single file, which could improve performance when using
72
82
// ...
73
83
$container->setParameter('container.dumper.inline_factories', true);
74
84
75
- Production Server Checklist
76
- ---------------------------
77
-
78
- These are the changes that you can make in your production server to improve
79
- performance when running Symfony applications:
80
-
81
- #. :ref: `Use the OPcache byte code cache <performance-use-opcache >`
82
- #. :ref: `Use the OPcache class preloading <performance-use-preloading >`
83
- #. :ref: `Configure OPcache for maximum performance <performance-configure-opcache >`
84
- #. :ref: `Don't check PHP files timestamps <performance-dont-check-timestamps >`
85
- #. :ref: `Configure the PHP realpath Cache <performance-configure-realpath-cache >`
86
- #. :ref: `Optimize Composer Autoloader <performance-optimize-composer-autoloader >`
87
-
88
85
.. _performance-use-opcache :
89
86
90
87
Use the OPcache Byte Code Cache
@@ -212,6 +209,120 @@ deployment process too):
212
209
used in your application and prevents Composer from scanning the file system for
213
210
classes that are not found in the class map. (see: `Composer's autoloader optimization `_).
214
211
212
+ .. _profiling-applications :
213
+
214
+ Profiling Applications
215
+ ----------------------
216
+
217
+ `Blackfire `_ is the best tool to profile and optimize performance of Symfony
218
+ applications during development, test and production. It's a commercial service,
219
+ but provides free features that you can use to find bottlenecks in your projects.
220
+
221
+ Symfony provides a basic performance profiler in the development
222
+ :ref: `config environment <configuration-environments >`. Click on the "time panel"
223
+ of the :ref: `web debug toolbar <web-debug-toolbar >` to see how much time Symfony
224
+ spent on tasks such as making database queries and rendering templates.
225
+
226
+ Custom Profiling
227
+ ~~~~~~~~~~~~~~~~
228
+
229
+ You can measure the execution time and memory consumption of your own code and
230
+ display the result in the Symfony profiler thanks to the `Stopwatch component `_.
231
+
232
+ When using :ref: `autowiring <services-autowire >`, type-hint any controller or
233
+ service argument with the :class: `Symfony\\ Component\\ Stopwatch\\ Stopwatch ` class
234
+ and Symfony will inject the ``debug.stopwatch `` service::
235
+
236
+ use Symfony\Component\Stopwatch\Stopwatch;
237
+
238
+ class DataExporter
239
+ {
240
+ private $stopwatch;
241
+
242
+ public function __construct(Stopwatch $stopwatch)
243
+ {
244
+ $this->stopwatch = $stopwatch;
245
+ }
246
+
247
+ public function export()
248
+ {
249
+ // the argument is the name of the "profiling event"
250
+ $this->stopwatch->start('export-data');
251
+
252
+ // ...do things to export data...
253
+
254
+ // reset the stopwatch to delete all the data measured so far
255
+ // $this->stopwatch->reset();
256
+
257
+ $this->stopwatch->stop('export-data');
258
+ }
259
+ }
260
+
261
+ If the request calls this service during its execution, you'll see a new
262
+ event called ``export-data `` in the Symfony profiler.
263
+
264
+ The ``start() ``, ``stop() `` and ``getEvent() `` methods return a
265
+ :class: `Symfony\\ Component\\ Stopwatch\\ StopwatchEvent ` object that provides
266
+ information about the current event, even while it's still running. This
267
+ object can be converted to a string for a quick summary::
268
+
269
+ // ...
270
+ dump((string) $this->stopwatch->getEvent()); // dumps e.g. '4.50 MiB - 26 ms'
271
+
272
+ You can also profile your template code with the :ref: `stopwatch Twig tag <reference-twig-tag-stopwatch >`:
273
+
274 + .. code-block :: twig
275
+
276
+ {% stopwatch 'render-blog-posts' %}
277
+ {% for post in blog_posts%}
278
+ {# ... #}
279
+ {% endfor %}
280
+ {% endstopwatch %}
281
+
282
+ Profiling Categories
283
+ ....................
284
+
285
+ Use the second optional argument of the ``start() `` method to define the
286
+ category or tag of the event. This helps keep events organized by type::
287
+
288
+ $this->stopwatch->start('export-data', 'export');
289
+
290
+ Profiling Periods
291
+ .................
292
+
293
+ A `real-world stopwatch `_ not only includes the start/stop button but also a
294
+ "lap button" to measure each partial lap. This is exactly what the ``lap() ``
295
+ method does, which stops an event and then restarts it immediately::
296
+
297
+ $this->stopwatch->start('process-data-records', 'export');
298
+
299
+ foreach ($records as $record) {
300
+ // ... some code goes here
301
+ $this->stopwatch->lap('process-data-records');
302
+ }
303
+
304
+ $event = $this->stopwatch->stop('process-data-records');
305
+ // $event->getDuration(), $event->getMemory(), etc.
306
+
307
+ // Lap information is stored as "periods" within the event:
308
+ // $event->getPeriods();
309
+
310
+ Profiling Sections
311
+ ..................
312
+
313
+ Sections are a way to split the profile timeline into groups. Example::
314
+
315
+ $this->stopwatch->openSection();
316
+ $this->stopwatch->start('validating-file', 'validation');
317
+ $this->stopwatch->stopSection('parsing');
318
+
319
+ $events = $this->stopwatch->getSectionEvents('parsing');
320
+
321
+ // later you can reopen a section passing its name to the openSection() method
322
+ $this->stopwatch->openSection('parsing');
323
+ $this->stopwatch->start('processing-file');
324
+ $this->stopwatch->stopSection('parsing');
325
+
215
326
Learn more
216
327
----------
217
328
@@ -225,3 +336,6 @@ Learn more
225
336
.. _`APCu PHP functions` : https://www.php.net/manual/en/ref.apcu.php
226
337
.. _`cachetool` : https://github.com/gordalina/cachetool
227
338
.. _`open_basedir` : https://www.php.net/manual/ini.core.php#ini.open-basedir
339
+ .. _`Blackfire` : https://blackfire.io/docs/introduction?utm_source=symfony&utm_medium=symfonycom_docs&utm_campaign=performance
340
+ .. _`Stopwatch component` : https://symfony.com/components/Stopwatch
341
+ .. _`real-world stopwatch` : https://en.wikipedia.org/wiki/Stopwatch
0 commit comments