62

My Symfony page isn't too slow (it loads in about 400 ms) but considering the fact that it's just a simple hello world page with basic authentication, it should be loading in less than 100 ms. When I enter the profiler, I see this:

Profiler timeline

Notice it just says "Firewall" for 250 ms. I thought the firewall was just responsible for keeping users out of certain areas of the page - I can't imagine that taking any longer than a few milliseconds plus the time it takes to fetch the user information from the database (which in this case is 61 ms).

Could somebody explain what the firewall actually does? If you have any general pointers on how to increase the firewall performance as well that would be greatly appreciated.


Note: I have Googled this of course, and I want to specify up front that I'm connecting to the MySQL database by IP address, not host name. This seemed to be the issue for every other case of slow Symfony firewall I could find.


Some resources from my project that could be relevant:

Hubro
  • 56,214
  • 69
  • 228
  • 381
  • 1
    I'd guess is executing all the rules in security.yml, the providers, acess control, and firewalls sections can get pretty nasty, checking all those for every request is time consuming. – MGP Apr 19 '13 at 18:47
  • @xr09: 251 ms is a *really* long time though (in computer time). I can't see any way simply reading the cached configuration and applying it to the security context could take anywhere near that long. – Hubro Apr 19 '13 at 18:53
  • I've just noticed, your `Astrups/SpectacleBundle/Entity/User.php` breaks the **Single Responsibility Principle**. – Yang Apr 20 '13 at 02:35
  • 1
    Try use some profile. XDebug and XHProf are really good. Moreover there is bundle for the second one: https://github.com/jonaswouters/XhprofBundle. It'll let you figure out which method are the bottleneck – Cyprian Apr 20 '13 at 14:33
  • 4
    I'd love to hear why this question was down voted – Hubro Apr 20 '13 at 17:09
  • Is this DEV or PROD build? Which version of Symfony2 have you? – gatisl Apr 20 '13 at 21:00
  • @gatisl: Not sure what you mean by dev/prod build, but the page is just as fast whether I use "app.php" or "app_dev.php". I'm using Symphony 2.2.1. – Hubro Apr 20 '13 at 21:18
  • @Codemonkey Yes, i meant prod/dev environments. Usually there is significant performance difference between both environments, because nothing is cached when dev environment is enabled. – gatisl Apr 20 '13 at 21:37
  • have you try using other security provider and/or encoder? – ihsan Apr 21 '13 at 01:43
  • Please check if you have APC installed. – NHG Apr 21 '13 at 03:11
  • @NHG: No APC installed. I'm just using vanilla Apache2 + PHP, freshly compiled. I'm currently trying to use XHProf to profile the firewall. – Hubro Apr 21 '13 at 15:39
  • I too had a similar issue once until I noticed that I had a ajax request that was loading forever from the previous request and it was blocking the firewall – Sethunath K M Apr 22 '13 at 05:40
  • Can you post the request sequence for this. Was it (get '/' -> get 'login' -> post 'login_check' -> get '/') or something else. That will help define what state the security system was in during this request. – james_t Apr 22 '13 at 17:45
  • @james_t: That's the login sequence, yes, but the request I'm profiling is just for "/" after login. – Hubro Apr 22 '13 at 18:25
  • @gatisl is right. Since you see the Profiler, you're in the DEV mode (app_dev.php). In this environment, no data is cached and additionally the profiler takes a while to load too. Try to clear your PROD cache using: app/console cache:clear --env=prod and then visit your website in PROD mode (app.php). If you did right, you wont see the profiler anymore and the page will load faster. More infos here: http://symfony.com/doc/2.1/cookbook/configuration/environments.html – Marc Juchli Apr 23 '13 at 09:31
  • @MarcJuchli: As I commented earlier, I have tried both environments and can't tell any difference in speed. It takes about half a second in both. Once I log out and visit the login page though, the page loads amazingly fast (less than 100ms). – Hubro Apr 23 '13 at 12:52
  • sorry didnt see this! But this could also be an issue of dns lookup. See: http://12wiki.blogspot.ch/2012/11/why-does-symfony-2-firewall-take-so.html – Marc Juchli Apr 23 '13 at 14:57
  • @MarcJuchli: I also noted in the question that I'm connecting to the MySQL server by IP address if that's what you're referring to. – Hubro Apr 23 '13 at 16:24

3 Answers3

13

I did some googling and I see that this guy, seems to have the answer to your question.

After 15 minutes of research I ended up figuring out that this was due to the PHP PDO constructor (my Firewall is the first to connect to the database as I use Entities as users). With this knowledge the issue was pretty quickly found ([1], [2]): as it turns out using a DNS name (like 'localhost') instead of an IP (like '127.0.0.1') causes this issue.

A simple edit of the parameters.yml file (changing localhost to 127.0.0.1) did the trick of reducing the Firewall load time to only a minimum.

Community
  • 1
  • 1
Rawdreeg
  • 461
  • 5
  • 12
  • For your information, [it's better](http://meta.stackexchange.com/q/8259) to include the essential parts of the answer here, and provide the link for reference. Since target resource is not guaranteed to be alive in the future. – j0k Apr 24 '13 at 07:25
  • 7
    I clearly specified in my question that this is **not** the issue. Check the **Note:** part. – Hubro Apr 25 '13 at 07:21
  • woooow! Thank you – peace_love Jul 30 '18 at 09:00
11

Alas, it turns out Rawdreeg was partly right. I made a 20 line PHP script to profile how long it takes to connect to my MySQL server:

<?php

$time = microtime(true);

$con = new PDO(...);

$connect_time = microtime(true);

$result = $con->query('SHOW TABLES');

$query_time = microtime(true);

var_dump($result->fetchAll(PDO::FETCH_ASSOC));

$time_con = ($connect_time - $time) * 1000;
$time_query = ($query_time - $connect_time) * 1000;

echo "Connection took $time_con ms\n";
echo "Query took $time_query ms\n";

The output was:

Connection took 230.18503189087 ms
Query took 64.532995223999 ms

Which fills the blanks of the Symfony profiler perfectly. The good news is that when my application goes live, it will connect to the MySQL server locally by socket, so it'll probably be blazing fast! There is little I can do about the speed during the development though, other than mirroring the MySQL server locally.

So to summarize the answer; the Symfony firewall initially creates the connection to the MySQL database, and in my case, that connection is quite slow. The MySQL connection time accounts for over 80% of the firewall's profiled time in my case.


Note: I'm already connecting to the MySQL server by IP address, and I've added skip-name-resolve to the MySQL configuration to no avail.

Community
  • 1
  • 1
Hubro
  • 56,214
  • 69
  • 228
  • 381
1

Your MySQL server might be the problem. Try adding skip-name-resolve to the [mysqld] section of your my.cnf file. This stops MySQL from doing a reverse DNS lookup on the IP address of incoming connections.

longneck
  • 11,938
  • 2
  • 36
  • 44
  • Thanks for the suggestion, I'll check that out. But wouldn't connecting to MySQL go under "Doctrine" in the profiler? – Hubro Apr 25 '13 at 17:41
  • I don't know. I was just going by the quote in Rawdreeg's answer that implies that the Firewall component is opening a/the database connection. – longneck Apr 25 '13 at 17:52
  • It didn't help unfortunately. Your answer did prompt me to write a script to profile the connection time though, which in turn answered my question. – Hubro Apr 25 '13 at 20:26