compul's avatar

Speed loss due to Cache usage

Hi,

I'm developing an API with Lumen for a Laravel app. The API will be required to support ~200,000 requests per minute in production. Taylor benchmarked 1800 requests per second for vanilla lumen on his laptop. On my laptop I run ~900/second for the Lumen welcome() page (though with eloquent and facades enabled, as well as a config file, a middleware and a service provider). However, when I run the API route that will be called 200,000 times a minute, I get only about 550/second. A bit of testing showed that as soon as I uncommented all calls to the Cache facade, speed went back up to ~750/second. I suppose the other ~200 are lost through the overhead of middleware and eloquent.

But how come loading Cache takes away that much? Multiple calls to Cache don't make a big difference, since Redis (which is what I use) is obviously a lot faster than a few hundred calls per second. I did not do any performance optimizations on Redis or Postgres or Nginx (those three are in use, though no database is being hit during that crucial route), though I did try whether enabling opcache made a difference (didn't).

Any idea whether there is a way to reduce that overhead of the Cache facade?

Also, would one win a lot of requests/second with eloquent & facades disabled, and all DB-interaction / Cache interaction done manually?

Thanks for any opinions!

Edit: requests/second were measured with apache-benchmark

0 likes
10 replies
jekinney's avatar

With out knowing how your sending request to your cache I'll have to guess your time issue is awaiting a ok response that a a method sent whatever to your cache.

On a laravel app I tested awhile ago (5.0) that firing an event to queue an email verses a method to send a queued email shaved off 300ms in time. In my case firing an event had almost 0 impact on time for the method to execute versus just building a queued email while waiting for the email to be built up.

compul's avatar

This is the function in question. There is no palpable difference between just using Cache::has() and Cache::put(). Simply using Cache somewhere makes the whole difference. Is there a way to not wait for that ok response (assuming this is the bottleneck)?

public static function heartBeat($uid) 
{
    if (!Cache::has('DEVICE.'.$uid))
            return config('ERROR');
        Cache::put('HEARTBEAT.'.$uid, '', 1);
        return config('SUCCESS');
}
jekinney's avatar

Not the way you have it set. It definitely is waiting for the ok, in your case success, that it was put on the queue. If you don't need the succes and check then yes.

compul's avatar

I would not need the 'ok' that it was put on the queue, however I obviously have to wait for the result of Cache::has(), and even using only this results in the same speed loss... And I don't think I can cope without that check. Out of curiosity, how would one avoid waiting?

jekinney's avatar

Try it for testing with just cache::put and immediately return ok response.

compul's avatar

I did try commenting the first two lines, but it makes barely any difference (maybe 10req/s).

Mike-e's avatar

Hi,

Don't use Façade to increase performance of your API.

Comment $app->withFacade(); in bootstrap/app.php file.

Regards.

compul's avatar

Hi Jaoued, thanks. I will try that. Do you have an idea how much that saves? Also, how would I best access the cache in that case?

compul's avatar
compul
OP
Best Answer
Level 1

Turns out that both Facades and Eloquent are a huge slowdown. Third place goes to dotenv. The others (middleware, service providers, config files) seemed to not slow it down too much. However, with Eloquent removed the main convenience of using lumen was gone, and it was still a lot slower than custom PHP. So I ended up deploying custom PHP for this particular simple but very high-traffic API. (Also for some reason laravel / lumen only has a drop-in for predis, not for phpredis, which is a bummer for production; so I obviously used phpredis for the API.)

1 like
NoorDeen's avatar

how did you benchmarked your api and found eloquent is the slowest piece in it ? if the way the query is generated is slowing eloquent you can generate the query once save it to cache and run it every time .

Please or to participate in this conversation.