littlebizzy / slickstack

Lightning-fast WordPress on Nginx
https://slickstack.io
GNU General Public License v3.0
629 stars 112 forks source link

How to speed up non-cached pages like cart and checkout? #136

Closed backamblock closed 2 years ago

backamblock commented 2 years ago

Hi, i have slickstack tested the last few days in a 2c/2gb VPS. The results for static pages are amazing and i also like the clean admin dashboard. However, while static pages easily handle 2k clients/sec with loader.io, the cart and checkout pages get up to 6000ms response times with even 20 clients/sec and 100% CPU load on both cores.

What can i do to improve this? thank you

jessuppi commented 2 years ago

Thanks for the feedback @backamblock

I guess the bigger question is "will you really have 2000 people per second loading your pages" and for most WordPress sites on a $5 cloud server the answer to that is nope.

SlickStack (and similar LEMP stacks) are used by many very high traffic WooCommerce sites without issue. It will skip the FastCGI cache if it detects the add-to-cart cookie generated by WooCommerce, and it will also skip the cache for a few specific pages like shopping cart, checkout, my-account (account), and contact page by default.

Enabling the Redis object cache can help with those dynamic pages. Currently this setting is SS_OBJECT_CACHE found within the ss-config file and will only be installed on production sites.

What else can help is simply upgrading your cloud server to more RAM and CPU, which results in exponential improvement... for example, 4 CPU cores is not only twice as powerful as 2 CPU cores, it's actually more than that. After you upgrade, you can run the ss-install again to re-optimize settings.

And of course, maintaining some basic security settings in Cloudflare also helps (e.g. rate-limiting) if you are worried about bad players attacking your site... but for most sites, it's just never an issue.

We could perhaps consider expanding SlickStack's rate-limiting rules to the cart/checkout/contact page too.

backamblock commented 2 years ago

@jessuppi You're probably correct. 2k page loads per second are some billions of site users per month. it's nice to see that it could easily handle that if needed tho. So my biggest respect for that!

Okay i will look into the config and test around a bit more. if the upgrade is that easy, then it probably won't be an issue at all. For the Object Cache: in some older issue you suggested to install the "redis object cache" plugin, but with my install i see a Drop-in already installed. So i don't need the redis extension anymore?

for the rate-limiting, as far as i understand that would only come into play when 1 IP opens the page multiple times. That shouldn't be an issue usually as you said.

thanks!

jessuppi commented 2 years ago

Thanks for the kind words!

About Redis object cache plugin, we have been force installing as a drop-in plugin the past few years. However, we've been discussing this recently because it's not really a good idea to do that without an easy "off" switch in WP Admin.

We will probably be moving back to using Till Kruss' plugin again:

https://wordpress.org/plugins/redis-cache/

If you have more feedback on that please join our Discord chat or open a related issue if possible.

for the rate-limiting, as far as i understand that would only come into play when 1 IP opens the page multiple times. That shouldn't be an issue usually as you said.

That is correct mostly it just prevents bots from attacking your site (on purpose).

backamblock commented 2 years ago

thanks, i'll open a new issue for the unrelated things :) i don't have discord unfortunately.

jessuppi commented 2 years ago

By the way, another approach to dynamic caching is using an HTTP output cache like Varnish which pretty much caches the hell out of anything and everything before the browser request reaches the actual server/PHP/etc.

But I've always hated using Varnish, because the price you pay for slightly faster speed is a lot of conflicts and problems... WordPress is just too dynamic esp. on the backend for output caching IMO. The same problems can be seen on Litespeed LS cache, which is pretty much a copycat of the Varnish structure.

backamblock commented 2 years ago

litespeed worked pretty well for me in UX with all the ESI and browser caching. but in the end the site was even slower with all the bells and whistles. the only thing that improved really was the initial spike with loader.io. but it was a hassle to install and set up. that cyberpanel makes my eyes bleed, those fonts 😆 i think the browser caching makes the most difference. when a site first loads it is okay when it is 100ms longer. the subsequent pageviews/clicking around is what is more seen by the user. for the cart and checkout, it will be okay. it would be nice but i don't expect a $5 VPS to handle 100 orders per second. when that is needed then there should be a budget for more powerful hardware as well 😄

jessuppi commented 2 years ago

i think the browser caching makes the most difference. when a site first loads it is okay when it is 100ms longer. the subsequent pageviews/clicking around is what is more seen by the user.

Browser cache headers can help, but again, they also cause problems like users seeing outdated pages... and it wouldn't be a solution for pages like shopping cart or checkout.

These days, modern browsers cache things even when you tell them not to, which is why we removed browser cache headers from SlickStack. And if you add HTTP output caching and/or object caching, the conflicts are even worse. I've tried to hold to the philosophy that stability is always more important than speed.

jessuppi commented 2 years ago

Just an update on this:

We are back to using Till Kruss' object-cache.php script in SlickStack and it will be installed on all production servers unless disabled in ss-config settings manually. We are not going to use the rest of Till's plugin to keep things simple, and going forward I think SlickStack will assume "object cache is a good thing, unless your site is poorly coded" instead of trying to offer so many different options to everyone... in other words, we will evangelize an object-cache.php for production.

We played with having object caching in staging, but it caused serious conflicts and we won't be doing that anymore... no more object cache in staging/dev sites going forward...

Also, besides object caching in production, "microcaching" a.k.a. dynamic caching is also being discussed:

Ref: https://github.com/littlebizzy/slickstack/issues/158

I think it goes without saying that SlickStack (and most Nginx stacks) don't mess with complicated things like ESI or ETag but those are offered in Litespeed as you mentioned... it's just too much messing around for me. In dynamic applications like WordPress that take so much maintenance already, dealing with that stuff is not worth the effort IMO.

Ref: http://www.itamarst.org/writings/dynamiccaching.html Ref: https://blog.litespeedtech.com/2017/11/01/wpw-friends-dont-let-friends-microcache/

...probably the first, and last time, I will link to Litespeed's blog ;)

For a more WordPress-specific solution that avoids the output cache mess of Varnish/LS Cache stuff, you can get into custom themes and custom cookies and stuff:

Ref: https://spinupwp.com/page-caching-personalized-dynamic-content/

But again, this is really not worth the time and effort for 99% of websites and agencies to worry about. For huge companies dealing with massive traffic and huge budgets, their dev team might consider doing this.

I also answered here, where I mentioned how KVM servers with NVMe drives and CPU-optimized are incredibly affordable these days and keep getting better, which also helps a ton:

https://wordpress.stackexchange.com/questions/405852/what-is-the-best-way-to-cache-pages-and-queries-in-wordpress

jessuppi commented 2 years ago

P.S. Another future-forward solution is doing ESI type stuff on the edge via e.g. CloudFlare Workers:

Ref: https://www.cloudflare.com/learning/cdn/caching-static-and-dynamic-content/