20

Note: Now that I know where the issue comes from, I modified the question. It now contains only the information needed.

I'm new to the Laravel PHP framework.

I have a very small app working on my computer. It is connected to a MySQL database and has a User model. I use the Auth class to log in and out.

Everything works fine, but when I am logged in, loading a page takes about a second which is very slow. When I'm not logged in, it's a matter of milliseconds.

By using the built-in profiler, I realized two problems. First, like I said, loading a page takes a bit more than 1000 milliseconds. Second, the framework makes one SQL every time I load a page when I'm logged in. The query searches a user with a certain id (my id). I guess it is there to get information about the logged in user. But isn't there supposed to be some sort of cache. Will this be a problem if my website will have to manage many requests per seconds.

I realized that using Auth::check() in the view is what is causing the issue. I have around 4 Auth::check() is my Blade view. When I have none, it goes fast. If I have one, it is slow. Then, no matter how many I have, it doesn't get much slower. It's like if the Auth class' initialization takes too much time or something like that. I guess it explains why it only happens when I'm logged in.

I dived into Laravel's code and I found out that when Auth::check() is called for the first time, the Auth class needs to "activate" my Session by retrieving the user's info from the database. That explains the query being executed every page request. But since the profiler says that the query doesn't even take a millisecond to execute, I still don't know why it slows down the app.

New information: Even when I'm not sending a query to the database, the simple act of connecting to it takes almost a second. This is the reason it is slow. I think I'm getting really close to solve the issue.

Any idea so far?

Thanks in advance.

Notes

  • The fact that Auth::check() is in the view doesn't change anything.
  • Using another method like Auth::guest() doesn't solve the issue.
  • New: Connecting to the database is what is slow.
Marc-François
  • 3,900
  • 3
  • 28
  • 47
  • That's quite interesting. I'm also new to Laravel, and have completed my first complete intranet package for my clients. It uses MySQL as well, but seems quite quick. The speed difference isn't that much on my system. Have you tried using Lavarel's cache yet? – Mike Rockétt Oct 11 '12 at 04:33
  • No, I don't use any cache. I expect Auth to do it by itself, no? Both the Cache and Session classes are configured to use the file system. If I have to cache my Auth variables manually, how would I do that? – Marc-François Oct 11 '12 at 04:35
  • Well, it wouldn't be Auth that's taking most of the time. I'm more concerned about caching the results of the database. As it stands now, Auth is quite good, and has no speed issues. – Mike Rockétt Oct 11 '12 at 04:38
  • And the caching tool is not automatic, so far as I know. Haven't had the need to use it yet. – Mike Rockétt Oct 11 '12 at 04:41
  • The database queries come from Auth. I don't use anything else. My application is still very simple. – Marc-François Oct 11 '12 at 04:42
  • I see. Could you share your views? – Mike Rockétt Oct 11 '12 at 04:45

2 Answers2

40

I finally found a way to fix this.

When reading some posts on many forums about XAMPP, MySQL, and PHP, and I read somewhere that it is preferable to use 127.0.0.1 because locahost needs an extra DNS lookup.

In the database configuration file, I simply changed locahost for 127.0.0.1.

Now everything is fast.

I find this really strange. Using locahost in the configuration file used to make the database connection take more than a second!

Marc-François
  • 3,900
  • 3
  • 28
  • 47
  • I'd like to know who else may be having the same problem. See, like I said in my last comment, my queries average less then a second, and I use a host-name lookup. In fact, I have a domain manager with plenty local domains. Yet, I haven't tried going back to IP... – Mike Rockétt Oct 12 '12 at 17:00
  • 7
    If the system is set up properly, there should be no dns lookup for `localhost`, as it should be in the `hosts` file on your system. I'd check that - it sounds like the result of an unusual dns setup – Adam Hopkinson Oct 12 '12 at 21:55
  • Thanks! I tried that on Windows using Z-WAMP (application/config/database.php) and there's a huge noticeable difference! – jpmonette Oct 28 '12 at 17:58
  • @marc-francois I'm curious about that problem. I assume you were experiencing this on a windows system? – dualed Jan 18 '13 at 08:41
  • 2
    Wow! Amazing. There is a huge difference in the project I'm developing after changing "localhost" to "127.0.0.1". When the database config was using "localhost" the time to load the page was 1,092.40ms. Now, after the change, is 58.36ms! – Fuhrmann Feb 18 '13 at 04:46
  • AMAZED. Didnt know one lookup would be this expensive. It's super-fast now. I always thought it'd be cached. – Deepak Thomas Jul 06 '14 at 15:11
  • This is strange. Does it also take long if you do `telnet localhost 3306` in the command prompt? Do you have `127.0.0.1 localhost` in your `C:\Windows\System32\drivers\etc\hosts` file? There shouldn't be any DNS lookup involved for `localhost`. – jbx Sep 09 '14 at 17:41
  • Based on this answer http://stackoverflow.com/a/16134366/905801, using `172.0.0.1` should be slower than `localhost` because the 1st will establish a TCP connection but the 2nd (`localhost`) will use a UNIX domain socket which is faster as per these benchmarks http://redis.io/topics/benchmarks – AbdelHady Apr 22 '15 at 13:52
2

I do not agree with Hammo's example. Having any user information other than their ID within the session is a security risk, which is why most frameworks take this route. Is there anything else being run when the user is logged in, apart from the query for their record? It's definitely not that that's slowing your application down.

Oddman
  • 3,715
  • 1
  • 16
  • 13
  • Well, except two or three `@if (Auth::check()) @include('some.stuff') @endif`, I don't know. – Marc-François Oct 11 '12 at 04:40
  • Are you doing the Auth check within the blade view? Is the include maybe slowing it down? – Oddman Oct 11 '12 at 04:41
  • Yes, the Auth check is done within the Blade view. The @include is for a simple menu and some links that I want to show or hide. – Marc-François Oct 11 '12 at 04:44
  • 1
    I can see where @Oddman is coming from, though I don't think it applies in this instance. None of that would take anything near 1000 milliseconds to render, though I can't confirm that for sure. Perhaps testing your speed by doing a calculation based on `LARAVEL_START`, and inserting a call to that just after every relevant call in your view should show you what's wrong. – Mike Rockétt Oct 11 '12 at 04:57
  • Thanks for the idea Michael. Now, I found more information about the issue. I edited the question with this information. – Marc-François Oct 11 '12 at 05:36
  • Yeah it seems very odd. Only thing I would suggest is disabling the view altogether and work at isolating the problem, bit by bit. Very interested to see what the issue is. – Oddman Oct 11 '12 at 05:36
  • It's quite interesting that `Auth::check()` is causing the problem... Have you tried `Auth::guest()`? Haven't looked at the underlying code yet (I'm at work at the moment). – Mike Rockétt Oct 11 '12 at 11:01
  • Alternatively, just run the filter on your route by passing the instruction as an array: `array('before' => 'auth'), function (x) ...`. – Mike Rockétt Oct 11 '12 at 11:07
  • I find this very interesting. My current intranet app (near completion, plenty tables and entries in each), and, when logged in, it averages 600ms (200 when logged out). So, I can't figure out. I'm sure somebody will be able to find the problem. – Mike Rockétt Oct 11 '12 at 13:53
  • That's really interesting - am going to do a blanket setup tonight when I get home and have a test for myself and see if I get the same results - it's definitely a massive jump. – Oddman Oct 12 '12 at 03:54
  • Ok thanks a lot. I found out that the connection to the database is the issue. We're getting close. I added information in the question. – Marc-François Oct 12 '12 at 05:04
  • @Marc-François Why don't you set a constant inside the before filter and set the constant value true or false. So inside ur view, you can avoid using Static method calls. Example USER_IS_LOGIN = Auth::check(); and put that inside the Before filter inside application/routes.php Give this approach a try. :) – Raftalks Oct 12 '12 at 23:26
  • Yes, that might be a better practice. I tried it and it didn't turn out to be the problem, which I solved as you can see in my answer. – Marc-François Oct 13 '12 at 01:49