Speed Up Your Site With Block Caching

Permalink 9 users found helpful
When it comes to the load time of a page there are many things that can effect the performance of a page. Block caching can be an effective way to increase the speed of your site.

First to demonstrate the effect in load time that block caching can have I created a two test blocks: "Benchmark Block With Cache" and "Benchmark Block No Cache". I will include the view.php files of each as this is the only thing that differs in the two blocks

Benchmark Block With Cache
<?php
  class BenchmarkBlockWithCacheBlockController extends BlockController {
    var $pobj;
    protected $btDescription = "A benchmark block for block caching with caching enabled";
    protected $btName = "Benchmark Block With Cache";
    protected $btTable = 'btBenchmarkBlockWithCache';
    protected $btCacheBlockRecord = true;
    protected $btCacheBlockOutput = true;
    protected $btCacheBlockOutputOnPost = true;
    protected $btCacheBlockOutputForRegisteredUsers = true;
    protected $btCacheBlockOutputLifetime = 300;
    public function view() {
      if($this->get('sql')) {
        $db = Loader::db();
        $res =$db->Execute('Select * from adodb_logsql');


Benchmark Block No Cache
<?php
  class BenchmarkBlockNoCacheBlockController extends BlockController {
    var $pobj;
    protected $btDescription = "A benchmark block for block caching with no cache";
    protected $btName = "Benchmark Block No Cache";
    protected $btTable = 'btBenchmarkBlockNoCache';
    public function view() {
       if($this->get('sql')) {
        $db = Loader::db();
        $res =$db->Execute('Select * from adodb_logsql');
        $abc = array();
        while($rs = $res->fetchRow()) {
          $abc[] = $rs['id'] * $rs['id'];
        }
      } elseif($this->get('curl')) {


The only difference between the two files are the Block Cache variables set in Benchmark Block With Cache
protected $btCacheBlockRecord = true;
    protected $btCacheBlockOutput = true;
    protected $btCacheBlockOutputOnPost = true;
    protected $btCacheBlockOutputForRegisteredUsers = true;
    protected $btCacheBlockOutputLifetime = 300


I ran one test with a sql query to a 4,299 record database table named adodb_logsql and one test with a curl request tohttp://pizzaface.tumblr.com

I added time the distance between the on_before_render and on_render_complete in the config/site.php site file with this
Events::extend('on_before_render',  'BenchmarkPageRender', 'startTimer', 'models/benchmark_page_render.php');
Events::extend('on_render_complete', 'BenchmarkPageRender', 'endTimer', 'models/benchmark_page_render.php');

And the benchmark_page_render.php file looked like this
<?php
class BenchmarkPageRender {
  public function startTimer() {
    Cache::set('benchmark_page_render', false, microtime(true));
  }
  public function endTimer() {
    $te = microtime(true);
    $ts = Cache::get('benchmark_page_render', false);
    $l = new Log('Page Render', true);
    $time = $te - $ts;
    $l->write($time);
    $l->close();
  }
}
?>


The results were as follows

Sql - Block Without Caching
9:47:57 PM Page Render 0.11348414421082
9:47:54 PM Page Render 0.123291015625
9:47:51 PM Page Render 0.11856198310852
9:47:48 PM Page Render 0.12127709388733
9:47:46 PM Page Render 0.099163055419922
9:47:43 PM Page Render 0.12289690971375
9:47:40 PM Page Render 0.12146806716919

Sql - Block With Caching
9:49:20 PM Page Render 0.031676054000854
9:49:18 PM Page Render 0.05222487449646
9:49:16 PM Page Render 0.044962882995605
9:49:13 PM Page Render 0.024227142333984
9:49:11 PM Page Render 0.03519606590271
9:49:08 PM Page Render 0.027742862701416
9:48:57 PM Page Render 0.047372817993164

Curl - Block Without Caching
10:02:35 PM Page Render 0.26554703712463
10:02:33 PM Page Render 0.25061106681824
10:02:31 PM Page Render 0.21851515769958
10:02:29 PM Page Render 0.23590183258057
10:02:26 PM Page Render 0.21153998374939
10:02:24 PM Page Render 0.23488306999207
10:02:22 PM Page Render 0.23919701576233

Curl - Block With Caching
10:03:53 PM Page Render 0.040138006210327
10:03:52 PM Page Render 0.038083076477051
10:03:50 PM Page Render 0.043893098831177
10:03:48 PM Page Render 0.035668134689331
10:03:46 PM Page Render 0.027914047241211
10:03:44 PM Page Render 0.027438879013062
10:03:42 PM Page Render 0.046179056167603

As you can see a significant difference in load time with just one block. The curl request is especially dramatic.

Now that we know that caching is important what can we do about it?

To enable block caching for you site go to Dashboard->Sitewide Settings->Speed Settings and set "Basic Cache to Enabled" and "Full Page Caching" to "Enabled if blocks allow it, unless specified at the page level."

The blocks themselves need to be written to support caching as well. There are five settings for block caching that are set in the blocks controller.

protected $btCacheBlockRecord

If set to true caches the block settings lookup
protected $btCacheBlockOutput

If set to true block output will be cached
protected $btCacheBlockOutputOnPost

If set to true the block output will be cached on post requests
protected $btCacheBlockOutputForRegisteredUsers

If set to true the block output will be cached for logged in users as well as guests
protected $btCacheBlockOutputLifetime

The length of time the block cache will last in seconds

Hope that helps to illustrate the importance of block caching and if there is anything I missed, got wrong or could be explained better let me know and I can add it in.

mkly
View Replies:
jordanlev replied on at Permalink Reply
jordanlev
This is super duper amazingly awesome. Thank you for putting this together, I think it should become a how-to.

I do want to mention one thing, though -- the loading of a C5 page involves a lot more than just displaying some blocks, and it's hard to say if this is micro-optimizing one part of the system that might not even be a bottleneck. I don't know if it is or it isn't, but I would suggest showing some benchmark numbers for the entire page load with these settings both on and off (and also for all blocks off, just one block on and the rest off, all blocks on, etc.). The reason I mention this is because the MISER library is the single biggest speed boost I've ever encountered with any of my sites, and that thing requires that block caching be turned *off* entirely. Which doesn't mean block caching is useless (MISER isn't appropriate for every situation), but does indicate to me that perhaps the bottlenecks in other areas of the system are much greater than the non-cached blocks bottleneck.

Anyway, I don't mean to be a nay-sayer -- I do think this is great information, and an essential part of the optimization toolkit. Just want to provide some more context for the overall picture.

Thanks again!

-Jordan
mkly replied on at Permalink Reply
mkly
Wow. Thanks so much. I'm glad someone finds this stuff useful. With all this talk about speed lately I figured it was time to get some actual data to talk about.

AFAIK Miser is about asset compression and concatenation which does little to improve on "first byte" response. I could be completely wrong on this and someone please correct me on this if I'm incorrect in this assumption.

A lot of "slow" sites I have seen on the forums have had long "first byte" load times which are typically AFAIK do to database/CPU/file load times probably do to resource starved shared hosting accounts.

That said, in many cases asset compression and concatenation is going to get you better results than removing database queries and removing curl requests. Also, throwing enough resources at a server that is not getting very high traffic can certainly make up for the lack of full page caching.

Of course I could be totally wrong about Miser not caching the page and block. Maybe I should do some benchmarks with Miser vs Full Page Caching next. :)

Thanks again for the kind words,
~Mike
jordanlev replied on at Permalink Reply
jordanlev
You're totally correct -- MISER is only asset caching. This is the reason I wanted to bring it up though -- while block caching is absolutely a critical piece of the optimization puzzle, it's always important to keep the big picture in mind and understand that there are other pieces as well, and sometimes the piece being focused on is much smaller than other pieces. Basically wanted to get that in the mix so people don't erroneously think block caching will solve all problems (I know you're not claiming that they do -- but sometimes people see a forum post and don't have the full context so they make assumptions).

But yeah, if someone's problem is "before the first byte", then MISER will not help in any way, and block caching will. Honestly, because of the incredible speed boosts I've seen from MISER, I kind of gave up on block caching altogether because I assumed it didn't really do much -- but seeing your benchmarks has made me reconsider that. This is why I think this post is so great, because it gave me some data to thin about as opposed to just gut feelings.

Thanks.
-Jordan
CIRESatCU replied on at Permalink Reply
Hi,

So when using Miser it is more or less use Miser OR use block caching? Am I understanding that right? Because Miser requires the caching to be off, the block caching wouldn't work?

It's been a while since this post, so I was wondering have you had better luck with Miser or block caching for your sites? I currently have Miser installed and it seems to have sped things up somewhat, but it's hard to say whether or not I can speed it up anymore. With YSlow my pages are now being rated around 96-100 and I've enabled gzip which helped a lot as well.

Any other suggestions that you might have, I'd certainly welcome.

Thanks,
Kiki
jordanlev replied on at Permalink Reply
jordanlev
Oh, and one other tiny thing -- the "var $pobj" is not necessary. I didn't know this until recently myself, but it's left over from a long long time ago and isn't even strictly valid PHP syntax (generates a warning in 5.3). Doesn't do anything in the system. I really wish they would clean up their sample block code, because it confused the hell out of me when I was first learning and is teaching an entire generation of C5 coders to do something that's wrong and not even necessary :(

(This in no way detracts from the main point of your post, though -- it's still awesome).
mkly replied on at Permalink Reply
mkly
Haha, thanks for that! I had always wondered about that one. Please feel free to correct me as much as possible. Whenever someone corrects me it means I've learned something new.
Phallanx replied on at Permalink Reply
Phallanx
@jordanlev

Now that there is a package for miser which uses the concrete5 render event, the requirement to turn off the cache might be moot (if using the package). I haven't investigated as yet, but it is on my list of things to do.

The original reason to turn off the cache was two fold.

1. Sometimes the call to render in the view.php was bypassed (therefore miser wasn't actioned). It may have been due to full page caching or something else, but I didn't investigate any further since Miser was superior in terms of speed with it off.

2. Cache was very "flakey"-it may have been fixed by now. I have never been convinced that it actually did anything to affect performance in a positive way. Benchmarks on my sites showed only negative performance impacts (without miser) but those sites were not heavy on SQL queries.

@mkly
Nice work. I haven't checked it out yet, but if it performs as you claim. I think a lot of developers are going to be quite busy if the core-team don't transparently do this. It's a good excuse for me to get off my arse and look at making miser compatible with the CC5 cache.
Tonero21 replied on at Permalink Reply
How can I implement this on my site. Can you please give steps I have to take to do this. Thanks in advance.
jordanlev replied on at Permalink Reply
jordanlev
Go to Dashboard -> Sitewide Settings, and make sure "Basic Cache" is set to "Enabled", and then under "Full Page Caching", check the box next to "Enabled if blocks allow it, unless specified at page level."
mkly replied on at Permalink Reply
mkly
After spending last night deciding how I'm going to delete several hundred thousand cache files I now recommend that you also set

"Full Page Cache Lifetime"
to
Custom - [ 1440 ]

Which is a day. You should adjust this for your site. For a small site you can probably get away with a week or more. But forever can get you in trouble if you have a lot of files and/or objects and attributes.
arcanepain replied on at Permalink Reply
arcanepain
Great insight here, Mkly! I too have spent quite some time trying to benchmark the cache and, thought most of my tests weren't nearly as precise as what you've done here, ended up settling on a combination of Memcache and APC (APC for opcode caching, only...cache layer set as 'memcached' in C5 site config).

E-accelerator used slightly less memory whilst running as the opcode cache, but APC just about beat it out speed-wise. X-Cache was also pretty fast, but kept doing weird things...caching things I didn't want it too and stopping forms from processing, etc... stuff like that.

Caching everything with this combo of Memcache and APC seems to work like a dream in simple cases where sites aren't updated often and are largely static...do find the occasional speed-bump when navigating the dashboard and/or dealing with sites which can't be cached quite so aggressively thanks to alot of dynamic content though. To this end, I came across your post about the compiled Adodb PHP extension, which i've just installed on one of my less mission-critical, largely-C5 tailored VPSs. So far so good and, anecdotally, things do actually seem snappier. This could easily be my imagination though...was just wondering if you'd had the chance to play around with the compiled extension much and whether you had any benchmarks like these here for pulling from database with this extension on and off?
mkly replied on at Permalink Reply
mkly
Hey thanks.
Some of the other stuff would have to happen at the code level I think. I did a test here. Between the various method of iterating a results set.

http://www.concrete5.org/community/forums/documentation_efforts/get...

GetArray should be the fastest with the extension turned on according to documentation, but I have yet to test that.

There are some more Adodb speed tips here

http://phplens.com/lens/adodb/docs-adodb.htm#speed...

When talking about highly dynamic content, a lot of what is not going to be cached ends up at the block level. I think in this regard for a high traffic site, it may be in your best interest to modify some code to take advantage of the above.

Also, adodb has it's own caching engine

http://phplens.com/lens/adodb/docs-adodb.htm#caching...

Again, you would have to modify some block code, but having a record caching layer that works in 15-60 second(or even a couple minutes) cycles certainly can't hurt on a high traffic dynamic site.

I also wrote a quick howto about using Zend Cache through concrete5 and its possible that you work with that as well

http://www.concrete5.org/documentation/how-tos/developers/configure...

Maybe we a get a little time this week I'll do some more tests and see what I come up with.

Thanks,
Mike

I made a very quick little addon that uses the adodb built in diagnostics to inspect some queries. I wouldn't run it on anything to mission critical, it's more for testing ect.

https://github.com/mkly/c5_addon_quick_database_check...
TheRealSean replied on at Permalink Reply
TheRealSean
Just a quick question in one of my blocks I think ripped from the slideshow block,

I notice that the core team use
protected $btCacheBlockOutputRecord = true;

is this same function as
protected $btCacheBlockRecord = true;?
or do they different things

/*edited*/
mkly replied on at Permalink Reply
mkly
lol. I just grepped it. That's the only place. Typo bug.
TheRealSean replied on at Permalink Reply
TheRealSean
Typical I copy the only place in the whole of c5 that uses that :)

I've updated my site, thanks
mkly replied on at Permalink Reply
mkly
Haha, I'd say send in a pull request but it looks like 5.5 already has it corrected.
programmieraffe replied on at Permalink Reply
programmieraffe
Does somebody have a solution for the "isEditMode"-Usage problem in custom blocks?

See here for details:
http://www.concrete5.org/developers/bugs/5-4-2/edit-mode-view-cache...

I disabled all cache settings by not so that I can use the isEditMode-method. How is the appropriate way to cache these blocks? Which cache settings can be turned on?
jordanlev replied on at Permalink Reply
jordanlev
What is the "isEditMode" problem (I've personally never ran into this, and the link you provided is to this page, which doesn't mention "isEditMode" anywhere)?
programmieraffe replied on at Permalink Reply
programmieraffe
mkly replied on at Permalink Reply
mkly
Ok. So after thinking about what are are doing in the end, it is true that this probably won't work either way, because the view will get cached either way.

You can set
$btCacheBlockOutputForRegisteredUsers = false;


This will prevent all registered users from caching.
mkly replied on at Permalink Reply
mkly
Ok so this is probably what you should do. If you are displaying something different to edit mode users then you should clear that pages cache. Maybe something like
$pg = Page::getCurrentPage();
if($pg->isEditMode()) {
  Cache::delete('page', $pg->getCollectionID());
}


I'm not positive at what point you will need to call that though. Hopefully that will get you started. But it's not a bug. It would be difficult/impractical for middle-ware to guess when a block view needs or doesn't need to be cached.
programmieraffe replied on at Permalink Reply 1 Attachment
programmieraffe
I agree that this is not a bug, just something that should be better documented for developers.

I ran a quick test with the following block settings:
protected $btCacheBlockRecord = true;
    protected $btCacheBlockOutput = true;
    protected $btCacheBlockOutputOnPost = true;
    protected $btCacheBlockOutputForRegisteredUsers = false;
    protected $btCacheBlockOutputLifetime = 300;


This worked for me. (I attached my cache settings.)

I think clearing the cache manually (as you suggested) would achieve the same but is maybe a bit more efficient because registered users can benefit from caching as well if they are not in edit mode.
programmieraffe replied on at Permalink Reply
programmieraffe
I just saw you suggested to clear the whole page cache, I assume that would be inefficient in most cases, so maybe it is possible to just clear the block from cache?
jordanlev replied on at Permalink Reply
jordanlev
Seems to me that setting $btCacheBlockOutputForRegisteredUsers to false is the most elegant solution. Clearing the whole page cache is the same as not caching in the first place (probably worse actually, because the cache is created, deleted, recreated, etc., instead of just never being created in the first place for certain users).

You're right that it should be better documented though. I don't even see block caching mentioned anywhere in the current dev docs :(
mkly replied on at Permalink Reply
mkly
@jordanlev

I guess it depends. If you don't use registered users then it would be better. If you have a lot of registered users then it's a bummer.

It's just one page... oh wait you could just disable the block caching
either
// in controller.php
public function on_start() {
  $pg = $this->getCollectionObject();
  if($pg->isEditMode()) {
    $this->btCacheBlockOutput = false;
  }
}

or this
// in controller.php
public function __construct() {
  parent::__construct();
  $pg = $this->getCollectionObject();
  if($pg->isEditMode()) {
    $this->btCacheBlockOutput = false;
  }
}

Try the first one first.

Either way none of this happens if we aren't in Edit Mode anyway. Is it really that important to maintain performance during the rare event of edit mode to slow all registered users in every case?
mkly replied on at Permalink Reply
mkly
That would only clear the cache for that particular page not the entire site. The only thing I'm not sure about is where to put that Cache::delete because it needs to be after the view() method. Maybe try this and see if it works?
// in controller.php of block
public function on_start() {
  $pg = $this->getCollectionObject();
  if($pg->isEditMode()) {
    $block_object = $this->getBlockObject();
    Events::extend(
     'on_render_complete',
     get_class($this),
     'delete_cache',
     $block_object->getBlockPath() . '/controller.php',
     array( 'page_id' => $pg->getCollectionID() )
    );
  }
}
public static function delete_cache($args) {


Might be some typo's in there. didn't test.
jordanlev replied on at Permalink Reply
jordanlev
Hmm... my head hurts.
Not sure how this fits in, but it looks like you can also call $this->refreshCache() in the block controller to clear that block's cache (seehttp://www.concrete5.org/documentation/developers/blocks/working-wi... )
mkly replied on at Permalink Reply
mkly
That was what I first thought. The problem AFAIK is that there isn't a hook to use that at the end of the block render/cache. So by then it's added to the full page cache and so that's why I thought you might have to throw an event all the way at the end of the page render with some "why people hate php" event extend code.
mkly replied on at Permalink Reply
mkly
I'll post what i just posted in that bug report

This is not a bug. That is how caching works.

1. You should be doing that in controller.php and passing it to the view.php as a value.

2. You should be doing that in on_page_view() in controller.php with
$pg = Page::getCurrentPage();
$this->set('isEditMode', $pg->isEditMode());

and then in view.php you should do
<?php if($isEditMode): ?>
  <?php //do something ?>
<?php else: ?>
  <?php //do something else ?>
<?php endif; ?>


Could you try it like this and see if you still have the issue? There may be something else going on as well.
fastcrash replied on at Permalink Reply
fastcrash
sometimes when i see a thread about speed, i got exited :), dont know why maybe it's natural, even in a games speed is crucial :)

mlky thats setting about block and talk is sure complicated :) --for me

i dont know abaout c5 cache mechanism, i not expert like u guys, but how about creating a file, a simple way about 'caching'?

in my test, i free 1 second with this(2.5s to 1.5s)
if (file_exists('./inc/header_menu.inc')) {
   include './inc/header_menu.inc';
   return;
}else{
         ...
   $file = "./inc/header_menu.inc";
   $write = fopen($file, 'w+');
   fwrite($write, $autonav);
   fclose($write);
}

i dont know where is the best place to put this in block, for now i just put it in view.php autonav block. i think about puting it in controller, can i?
tobi replied on at Permalink Reply
Hi everyone,

thank you for this great discussion. I tried it out (on a test site - 5.6.1.2) but i saw the biggest improvement in time to first byte when chosing under Dashboard - Full Page Caching - "On - in all cases" (maybe i missed some blocks?).
I'm not sure if this "forced" option was available back when you wrote this post. So given it's available now and it helps why bother to define the caching settings for each block individually?
Or which are the blocks we wouldn't want to cache?
I'm sure they exist, so would there be a way to exclude those few from caching under "on - in all cases" rather than including all the others one by one?

sorry for all the questions. I ask because this seemes to me like the most relevant thread addressing the issue "time to first byte". So now it's about how to implement this in the most practical way.

Thanks
Tobi
JohntheFish replied on at Permalink Reply
JohntheFish
On any block where the block view or a template for the block view shows dynamically generated content, then block caching will show the content at the time the block was cached, not at the time the block is shown.

As a trivial example, suppose you had a template for the content block that, as a footnote, appended the current user name, date and time to that block.
(its a bit contrived, because most developers wanting to do something like this would create a dedicated block)

With block caching off, the information would be correct. With block caching on, the information would be wrong.
tobi replied on at Permalink Reply
Hi John,
what a the speedy reply! You're absolutely right @ dynamic content. So i'll have to check case by case what is needed. If it's just an informational site with a few updates here and there i could run a job to clear the cache e.g. every day and leave cache "on - in all cases".
in case i need dynamic content i guess i'll have to go through the packages / controller.phps to add this as most add-ons in the market place don't have this in-built (only the core blocks typically have)...
thank you for clarifying that.
Tobi
JohntheFish replied on at Permalink Reply
JohntheFish
I have a free Cache Vac job in the marketplace.
http://www.concrete5.org/marketplace/addons/cache-vac/...

And a Cache Filler job (though you will probably use wget)
http://www.concrete5.org/marketplace/addons/cache-filler/...
JohntheFish replied on at Permalink Reply
JohntheFish
I am also pushing for the core to include a user selective control of the block cache as there is with the page cache (link to the leaders forum)
http://www.concrete5.org/developers/pro-accounts/community-leaders-...
Phallanx replied on at Permalink Reply
Phallanx
@JohntheFish

I don't think we should confuse full page caching (FPC) with block caching.

Full page caching gives us the opportunity to make a page behave as if it were static HTML. The clue here is in the name "static". Dynamic content is not static, therefore a block that serves up such content cannot be cached and CC5 quite rightly turns off full page caching for that page unless you specifically override it.

There are many, many addons/blocks that "could" work nicely with full page caching that currently do not and it has more to do with the way the block is written rather than being dynamic content. (See my comment here for a suggestion about marking blocks that inhibit FPChttp://www.concrete5.org/community/forums/customizing_c5/concrete5-...

Therefore I propose that the FPC is doing what it is designed for, improves many sites performance and doesn't need to be modified/fixed/changed.

The issue then is what about dynamic content blocks that prevent FPC. The fact is that the underlying structure of CC5 is relatively unchanged and still slow (most of the performance gain from FPC is the early invocation before attempting to load stuff) and we are back to slower TTFB times but, importantly, nowhere near as bad for the edge cases of 10+ seconds due to the zend cache.

The biggest single bottleneck is the OnPageStart so, if you have lots of blocks that have code in here (or the same block several times) , then you are stuffed - regardless of block caching. Addons that don't have code in here still have an overhead (since it is always invoked for all blocks) but this is minimal. I expect those blocks that do have code in the OnPageStart would define that they need to be executed and therefore selectively executing them would make little difference. The only way (currently) is not to put code in there or for the block to enable it's own file based cache so that cached content can be reused between blocks of the same type if there are several on a site/page. Again. If new content is required on every page view for each block(a usec timestamp, for a simple example) then you will never be able to take advantage of caching of any type and if something can be cached. The only person that knows what, where, how long and how much is the block developer.

I'm not saying I have the answers. But I think I understand the problems. Adding more options to FPC in the CC5 core just complicates without resolving the issues, I think.
mkly replied on at Permalink Reply
mkly
Hi Everyone,
Good to hear your insight @Phallanx. I've made a note to bring up your suggestion about a marker for blocks that support(or do not support block caching).

I think what you are saying about FPC now solving one particular problem(server content without ever hitting the database), is pretty much where we are on that. We had a conversation about that yesterday and I brought up issues like paging not working with FPC and was told that people should simply not use FPC if they need stuff like that.

With that said, I don't really think FPC will be intended for the same general site use it once was. It is for highly static public sites with high traffic more than a general faster than block caching type use case. From what I understand at this point, the vast majority of sites probably will not have a use case for FPC and now depend mostly on the faster light block caching now implemented.

Best Wishes,
Mike
JohntheFish replied on at Permalink Reply
JohntheFish
Whilst there are plenty of places where I think the cache strategy fails to meet edge cases, the one I feel would really make a difference is site admin control of block caching.

Being able to switch off block caching in spite of what is coded into the original block controller, on a block-by-block or page-by-page basis, would mean that uses of a block that take it outside its cached capabilities would no longer result in block cache for the whole site needing to be regularly flushed or switched off.

In the other direction, I suspect there are blocks with caching disabled simply because the developer found an edge case that didn't fit in with the block cache, or simply decided to play it safe. So an ability for a site admin to force block caching on for a specific block could also be of benefit.

More generally, no matter how sophisticated a cache system is, it will never be perfect. Even if c5 was re-designed from the ground up about another new cache system it wouldn't be perfect. There will always be minor issues somewhere or other. Selective control of block caching would provide a 'get out of jail card' for such issues while waiting for the next version of c5 to fix them (or not fix them).
Phallanx replied on at Permalink Reply
Phallanx
@JohntheFish
Sorry. In my previous post "OnPageStart" should be On_Start.

</quote>
Being able to switch off block caching in spite of what is coded into the original block controller, on a block-by-block or page-by-page basis, would mean that uses of a block that take it outside its cached capabilities would no longer result in block cache for the whole site needing to be regularly flushed or switched off.
</quote>

This is what I was saying about confusing block cache with FPC. Please correct me if I'm wrong, but it seems that you believe that block cache caches a blocks content. It doesn't. All the settings in the block controller dictate under which conditions the FPC can cache the content. The block cache basically caches a list of all the php content of blocks for a page so that it doesn't have to find, load and regenerate the list of blocks on a page. Unless you dynamically change the block code, I sees no reason to not cache this data unless the blocks on the page are added or deleted (i.e.at edit time).

<quote>
In the other direction, I suspect there are blocks with caching disabled simply because the developer found an edge case that didn't fit in with the block cache, or simply decided to play it safe. So an ability for a site admin to force block caching on for a specific block could also be of benefit.
</quote>

This is why I suggest the markers on the block (not because of the block cache but because of the FPC-see above). If developers see that it is preventing FPC then maybe they will make more of an effort to understand the block variables that control it. Additionally. If there is a visual indicator that a block is preventing FPC then the PRB can request that a developer justify why a block is preventing it. Blocks playing nicely with FPC should be the norm IMHO and that is the responsibility of the developer rather than CC5.

<quote>
More generally, no matter how sophisticated a cache system is, it will never be perfect. Even if c5 was re-designed from the ground up about another new cache system it wouldn't be perfect. There will always be minor issues somewhere or other. Selective control of block caching would provide a 'get out of jail card' for such issues while waiting for the next version of c5 to fix them (or not fix them).
</quote>

The big changes from previous versions to the current one in terms of performance is

1) Removal of Zend.
2) Early invocation of the FPC (90% of pages do not allow FPC because of at least one block, hence most people select "On In All Cases").

The block cache has changed very little-a few tweaks here and there.

Block cache, whilst arguably improves performance, comes quite late in the load process. In the past it was one of the bottlenecks because the entire load process was a bottleneck. Without FPC this is still true but alleviated by the removal of Zend. Currently, however, if FPC is not enabled for a page, then it is the On_Start that is the problem, not the block cache. I see little benefit in twiddling with block cache whilst developers are using the On_Start feature - of which there are relatively few blocks.
JohntheFish replied on at Permalink Reply
JohntheFish
I am well aware of the difference between the block cache and the page cache.

In 5.6+, when block cache is enabled and the flags in the block controller permit, the output of the block is generated when the edit dialog is saved and attached to the block record in the database. Then, when the block is viewed, that record is retrieved and served instead of rendering the block from scratch.

This immediately raises an issue that didn't exist in previous versions of concrete 5 - The block is rendered in the context of wherever it was saved: while the isEditMode() test is 'true'; in the context of a stack in the dashboard stack edit page; when setting page defaults; the current user is whoever it was saved by. Blocks that have context dependant behaviour (in the controller or in the view) that used to behave acceptably with the block cache enabled (or acceptably within constraints) no longer do so.

One of the roots of this problem is precisely because the block cache takes its final instructions from the flags hard coded into the block controller. At the moment, if a site with block cache enabled has a situation where those flags are inappropriate, you have the options to:

- Turn off the block cache for the entire site (so loosing the benefit on unaffected pages)

- Write code to override the block controller with different flags (a site specific solution, again with impact on otherwise unaffected uses of the block)

- Get the developer of the block to change the flags (which hobbles all other uses of the block)

What I advocate is a more general mechanism where a site owner can go into page properties or block design and override those settings from a dialog.

Any cache related problems for a bock can then be patched where they occur.

Such a control already exists for the page cache on a page-by-page basis.

As a purist, I agree that in a perfect world the design of blocks and a caching mechanism would be so faultless that such a control would never be necessary.

As a pragmatist, I conclude that such perfect behaviour will never exist. Block controllers are coded by developers who can never anticipate all the uses a block will be put to. Block views are added by other developers who did not set the original flags.

So with my advocated dialogue, the flags currently in the block controller would be advisory or defaults, but not absolutes.
WebSolutions replied on at Permalink Reply
WebSolutions
Great tutorial, thanks! I've enabled block caching on a custom block, the block is in a stack for a right sidebar. I notice by the speed of page load that the block caching has to happen per block per page -- ie. if I click About Us, it caches, and I can access About Us quicker next time, until my cache expires, but if I go to Contact Us, even though it is the same block/stack, it has to "re-cache". Is there any way to have the block cached overall so that any page that it appears on already has it cached?
hissy replied on at Permalink Reply
hissy
This is a great documentation and interesting discussion, but I still have a question about caching.
How long time of block caching if $btCacheBlockOutputLifetime will set to 0?
Example, page_list has 0. Page List block will not updated until manually updated or cleared?
TeleFox replied on at Permalink Reply
Will definitely try to incorporate this