Jump to content

TTFB extremely slow... caching options discussion


a-ok
 Share

Recommended Posts

Hi everyone

I’m super close on launching a site I have been working on for a while but upon some final testing the TTFB on the site is super slow... like 6s slow which is madness.

The site uses a lot of page queries and includes but apart from that it’s generally pretty fast – the load times after TTFB are fine.

I’m wondering about a few things...

1. ProCache – this works amazingly well when enabled but of course each page has to be cached first and if the TTFB on each is slow then do you think it’s a redundant move? Is there a way to cache the pages without visiting each one? And do you think if a page is saved the default should be to empty the cache for the whole site? Be nice to get some feelings on best practice for this.

2. I use a lot of includes (.inc) in my templates as I try to build everything quite modular. Is there a better way to do this (render?) or is this generally fine?

3. Template cache – would this help with TTFB or rather the issue is with the MySQL pages queries so template caching wouldn’t help with this. I’m a little confused on template caching...

3. Markup cache – could this be used for improving TTFB DB queries or not?

Thanks everyone... just keen for a bit of discussion and best practice on this.

Link to comment
Share on other sites

What's the TTFB of a procached version of a page X (a complex one)?

I think template cache will not get you any advantage over ProCache, but MarkupCache will as you can cache parts of the page before ProCache kicks in! 

Use markup cache for blocks of code that do complex queries or when querying multiple pages.

Basic example: A website has hundreds of podcast episodes. You can cache a count of these episodes so you don't need to query it when the page cache is cleared in ProCache.

$template = $templates->get("podcasts"); //episodes
$all_episodes_count = $cache->get("all_episodes_count", $template, function($page) {
  return $page->NumChildren(true);
});
$view->total_episodes = $all_episodes_count;

The "all_episodes_count" cache file will only be cleared when a new page is created with the template "podcasts".

 

  • Like 2
Link to comment
Share on other sites

6 hours ago, Sergio said:

What's the TTFB of a procached version of a page X (a complex one)?

81ms :)

6 hours ago, Sergio said:

Use markup cache for blocks of code that do complex queries or when querying multiple pages.

Ah yes I was reading about WireCache... is it possible to declare more than one template in the get statement?

$template = $templates->get("events-detail|guides-detail"); // But this of course only grabs the first
$articles = $cache->get("wtg", $template, function($pages) {
	return $pages->find("template=events-detail|guides-detail, sort=sort");
});

Thanks for your help!

Link to comment
Share on other sites

Also this seems to be working but is this all correct?

	$eventsDetailTemplate = $templates->get("events-detail");
	$wtgDetailTemplate = $templates->get("where-to-go-detail");
	$mtlDetailTemplate = $templates->get("meet-the-locals-detail");

	$related_events = $cache->get("relatedEvents", $eventsDetailTemplate, function($pages, $page) {
		return $pages->find("template=events-detail, id!=$page, location_venue!=$page, tags=$page->tags, events_detail_dates_final_date>=today, sort=random");
	});

	$related_wtg = $cache->get("relatedWTG", $wtgDetailTemplate, function($pages, $page) {
		return $pages->find("template=where-to-go-detail, id!=$page, tags=$page->tags, sort=random");
	});

	$related_mtl = $cache->get("relatedMTL", $mtlDetailTemplate, function($pages, $page) {
		return $pages->find("template=meet-the-locals-detail, id!=$page, tags=$page->tags, sort=random");
	});

	$related = $related_events->import($related_wtg)->import($related_mtl);
	$related->sort('random')->filter("limit=4");

 

Link to comment
Share on other sites

13 hours ago, oma said:

The site uses a lot of page queries

It's this part that probably has the most impact on performance.

 

1 hour ago, oma said:

Also this seems to be working but is this all correct?


	$eventsDetailTemplate = $templates->get("events-detail");
	$wtgDetailTemplate = $templates->get("where-to-go-detail");
	$mtlDetailTemplate = $templates->get("meet-the-locals-detail");

	$related_events = $cache->get("relatedEvents", $eventsDetailTemplate, function($pages, $page) {
		return $pages->find("template=events-detail, id!=$page, location_venue!=$page, tags=$page->tags, events_detail_dates_final_date>=today, sort=random");
	});

	$related_wtg = $cache->get("relatedWTG", $wtgDetailTemplate, function($pages, $page) {
		return $pages->find("template=where-to-go-detail, id!=$page, tags=$page->tags, sort=random");
	});

	$related_mtl = $cache->get("relatedMTL", $mtlDetailTemplate, function($pages, $page) {
		return $pages->find("template=meet-the-locals-detail, id!=$page, tags=$page->tags, sort=random");
	});

	$related = $related_events->import($related_wtg)->import($related_mtl);
	$related->sort('random')->filter("limit=4");

 

If that is just to find four random items it could be done a lot more efficiently as:

$related = $pages->find("id!=$page, tags=$page->tags, (template=where-to-go-detail|meet-the-locals-detail), (template=events-detail, location_venue!=$page, events_detail_dates_final_date>=today), sort=random, limit=4");

When you are wanting a specific number of results, wherever possible you should do that via a limit in the database query i.e. in the $pages->find() selector.

Edited by Robin S
Corrected $pages typo.
  • Like 3
Link to comment
Share on other sites

Thanks for your help, everyone.

ProCache is working pretty well – it's just that initial load per page (before it's cached) that's causing me a few problems as that initial load is slow.

I have about 3 $pages->find() queries on one of my pages where the initial load is slow – each of them querying about 150 pages. This would cause such slow initial load, right?

Link to comment
Share on other sites

Also if anyone has any suggestions on how to use WireCache $cache with multiple templates?

$articles = $pages->find("template=where-to-go-detail|our-guides-detail, sort=sort");

The below doesn't work and returns the following error (which I guess is because I'm using $templates->find() rather than $templates->get() and the $cache expected a single template?

PHP Notice: Object of class ProcessWire\TemplatesArray could not be converted to int in

$template = $templates->find("name=where-to-go-detail|our-guides-detail");
$articles = $cache->get("wtg", $template, function($pages) {
    return $pages->find("template=where-to-go-detail|our-guides-detail, sort=sort");
});
Link to comment
Share on other sites

53 minutes ago, oma said:

Also if anyone has any suggestions on how to use WireCache $cache with multiple templates

I never used this approach for more than one template, but you can also use the $expire parameter:

    $all_matches = $cache->save('all_articles', $pages->find("template=where-to-go-detail|our-guides-detail, sort=sort"), $expire = 432000); //week

 

Link to comment
Share on other sites

5 minutes ago, Sergio said:

I never used this approach for more than one template, but you can also use the $expire parameter:

Thanks, Sergio but I was wanting to do a check if a page using either the template where-to-go-detail or our-guides-detail is updated to reset the cache... whereas you can seem to only check one template.

Link to comment
Share on other sites

8 hours ago, oma said:

I was wanting to do a check if a page using either the template where-to-go-detail or our-guides-detail is updated to reset the cache

See this blog post where it talks about using a selector string as the "expires" argument.

But before you go too far into WireCache as a solution for your problem I recommend going through your PageFinder queries ($pages->find(), $page->children(), etc) to see if they can be optimised. You might find you don't need WireCache then - for example, if you change to the query I suggested in my previous post you probably wouldn't need to cache it.

9 hours ago, oma said:

I have about 3 $pages->find() queries on one of my pages where the initial load is slow – each of them querying about 150 pages.

It's not so much how many pages you are querying that matters, it's how many pages your query is returning. If each of your 3 queries returns 150 pages then this is not ideal unless you are actually using 450 pages in your markup somehow. Your aim should be to return no more pages that you are actually going to use. Also try to avoid multiple PageFinder queries if the same result can be achieved in one query (as demonstrated in my previous post).

 

Link to comment
Share on other sites

Thanks for this, Robin.

One query is returning 60+ results... no pagination. As soon as I add a limit to it (18) it’s a lot faster. Guess that’s mainly it, right? Interesting to know re the wireCache... but apart from the odd few queries that I will make more efficient I guess it’s down to what’s being returned (rather than queried as you say).

Link to comment
Share on other sites

12 hours ago, oma said:

Thanks, Sergio but I was wanting to do a check if a page using either the template where-to-go-detail or our-guides-detail is updated to reset the cache... whereas you can seem to only check one template.

You can use a hook in ready.php to delete cache on save of pages

// delete caches when pages are created, saved or moved around
wire()->addHookAfter('Pages::save', function(Hookevent $event) {

  $page = $event->arguments(0);
  // do nothing on admin pages
  if($page->template == 'admin') return;
  
  // delete cache for templates  
  if($page->template == 'where-to-go-detail' || $page->template == 'our-guides-detail') {
    $this->cache->delete('wtg');
    // here you could add logic to rebuild the cache
  }
  
});

 

  • Like 5
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...