 Thank you for being here. My name is Mark Molinari. I work for Taguan Consulting. I'm here with Fabio Franza, who also works for Taguan, and Wim Leers, who works for Acquia. We are going to talk about render caching in Drupal 7 and Drupal 8. So I will start with the current state of render caching in Drupal 7. There's a control module which is called render cache. Does anyone use that module? Please raise your hand. One, two, three, four. Okay, that's not surprising because the current usage of this module is really low. 31 sites. And that's from yesterday. Well, we hope that at the end of this session, you will take a look at that. So what is the problem? The problem is that the building and rendering entities can be slow. That's not something that you generally see at the beginning of a new project. It takes a while. Maybe you don't even see at the end of the project, and you start seeing this problem when the site gets populated, when there are more entities, especially on pages that show multiple entities. And so what happens is that when you get a call from your client who says, the site feels slow, especially some pages. Sure, sure, thank you. Okay, thank you. So, thank you. So the site feels slow, especially some pages. And then you take a look and you see something like this. So the database is fine, obviously, 70 milliseconds. But page execution time is almost 1.5 seconds. What's going on? You profile it and you see something like this. Render, render, team, render. Well, when you see this, you have the kind of problem that render caching might be able to solve. This actually might be my most important slide. If you see this, then investigate render caching. And so you try to solve it. And there are ways to solve it. There is an existing solution for Drupal 7. Render arrays have a cache property. You take a look and you see something like this. Oh, that's great. We have a cache property and we have keys. We have our bin, expire, granularity. So that's great. We're done. It's solved. And actually it's not solved. Because if you try this code, what happens is that you actually see cached content. You see there's a time call. You will always see the same time for a minute or so. But actually that won't help you. Because right now you are defining your cache property and you're also defining the heavy duty. It's the markup you want to cache. It's the process of creating this markup that you want to cache. And so you are just doing the same thing. You're showing cached content, but you're not saving time. The correct technique to do this is something like this. So you don't set the markup, which is very quick. You use pre-rendered functions. You set your cache keys. And then in the pre-rendered function you do your expensive task. And this works. Because what happens is that render, the drooper render, if the drooper render finds a cache, it will use the cache. Otherwise it will call the pre-rendered function. And then it will cache it. So yes, this works. But it's a little, it's not really elegant. It's almost a hack. And it's also very low level. And also you have the problem of caching validation. I mean, yes, it's cache. So it's supposed to show content, which is not always up to date, but still. And so this is, by the way, from the render example module. So it's sort of the official way to do this. Has anyone ever used this technique? Yeah, just one, two. Okay. And that's typical because it's too low level. Okay. We believe there's a better solution. And the better solution, oh no, sorry. The better solution. Oh yes, these are two blog posts. I try to be as quick as possible about the current technique. If you did not understand, take a look at these two blog posts, they explain it very well. So there is the render cache module for Drupal 7, which is simpler. It's more powerful, more elegant. And I am now going to show you a demo of this. It's not going to be anything fancy. It's a very, very simple site, just core features, views. I use devil generate to populate it. I created 50 article nodes, one page node with the 300 comments. And I just added one line of custom code, which is this one. And we will get there later. And we will look at two pages. One page is a view, which shows the 50 articles. And the other page is the page node with all those comments. This is the site, really. So very, very simple. This is the view. It's just plain Drupal. That's a view. Then we have the page with the comments. And yes, it's a popular site. A lot of comments. But nothing special. And I didn't use anything. I didn't use memcache. I didn't use entity cache. No tricks, nothing. Okay? And so I am actually going to run some benchmarks on this site. The benchmarks are something like this. I will disable render cache. Then I will just load one page to be sure the caches are warm. I will load the pages a bunch of times. And then I will do the same with render cache. And so let's take a look. Okay. Let's start with the view. It has disabled render cache. And now it's running. I will split the window so we can compare. This is not how we load test sites. It's just a patch benchmark a few times. So just, oh, there it is. So this is the result without render cache. We got about nine pages per second. Okay? So in such a simple site, what kind of performance increase would make you happy? Like 15% or 30%? What about like 50%? If we get to 14 pages per second, let's see. It's a simple site, okay? Let's see. Yeah. Yeah. We got 26 pages per second. Okay. Let's run. Thank you. Thank you. The applause really goes to Fabian because he's the main architect of this. But thank you. So let's try the node. Now it's disabled. It will run. Yeah, it's slow. If you want to tweet about that, you can use hashtag Drupal perf. Okay. We got our results. We got three pages per second. Now think again, what kind of performance would you like to see? Three pages per second. Let's see. We got 14 pages per second. Yeah. It's amazing. Okay. So let's move on. Okay. So this is, well, you've seen that, but this is a chart which shows what we see. It's a mean page request time, but it's essentially the same thing. And if you take a look, if you profile and compare, that's what you see. Okay. This is kind of performance you see. It's amazing. But this is a test site. What about a real example? Well, render cache module is not used in many sites, but one of those sites is actually Drupal.org. And this is an example of Drupal.org. So take a look. It's a page with 220 comments. And that's the kind of increase that we saw. And what about caching validation? Well, let's try. So I have my view. I open, actually I have to open it in another window. Hmm. It's big. Okay. So I edit it. And I add, hello. I save it. Okay. And now I go back to my own page. And it's done. And the page is still fast. And it's automatically invalidated. So we didn't have to wait any time. It just worked. Now I will show you why. Okay. Let me take. Okay. Why does this work? Caching validation? Well, let's see how to use this module. It's almost turnkey, almost. It includes integration with comments, context, display suite notes and views. It also works with custom entities as long as you use the entity API. And it has these four hooks that you can use to customize render cache. And they essentially enable you to change these things. First of all, the cache info, which is always the same key. So being expired granularity, you should just leave keys alone. And then that render cache, render to markup flag, which by default is false, but that's for historical reasons. You should just set it to true. In general, you will not have issues. It's actually more complicated than that. There are some special cases. We don't have time to talk about that now. And actually, a new version is coming out. So that's not really a problem. And you also have a hook to define the hashes you want to use. By default, it used the entity ID, the bundle, the modified time, and the view mode. And that modified is the reason why invalidation just works. Because hashing the modification time of the entity makes sure that you always, you're always displaying automatically the updated entity. And you can also, there's also a hook for the cache IDs that you can also alter. And so how to use it? I am really running out of time. So very quickly, this is how it was implemented in Drupal.org. The first hook essentially says do not use render cache. The second hook says, no, okay, use it for comments. And this is the interesting hook which sets the hashes to set the interesting hash is this one. Comment to ID modified. So since users are displayed in comments on Drupal.org, we had to make sure that whenever the user was updated, the comments were updated too. And so we used this hash to also save the user, the last time the user was modified. And then of course the comment is different if the user is the viewer or if he's the author and so on. And so, very quickly, embedded entities, just like the example I just said, users inside comments, you need to make sure that your hash is considered that. You have to think in entities sort of. What I mean is it's a good idea to think in entities anyway. It's a very clean way to build a site. For example, this means that when you create a view, you should try to use entities and view modes and delegate to view modes what you're actually showing. If you pick fields and display those fields, entity render cache won't be able to help you. That's actually not true because Dave Raid just posted a patch to support that. So it's still moving. And finally, permanent caches. Currently, render cache has a permanent cache. We generally use memcache and so that's not a problem. Using memcache is also a good idea for other reasons because memcache just garbage collects the cached items which are not used. But if you use the database has cache back end, then you will need to take care of that. And I'm done because it's very late. So after seeing those caveats, let's close all our eyes. No, probably not. To dream a little of what the future of this module could be. And so the ideal case in an ideal world would be that really we have a page and Drupal is loading the page and it says, oh, wow, the header and the footer region I've already cached. So just display that, get it from the cache. Then you have the content region and you have a listing there and the main output is cached as well. So then in the listing, you know that two of those three nodes are already cached but one node is not. So all you should be seeing in your page request is kind of one Drupal render to render this node that's not already rendered and the rest should just be automatically. However, as with all perfect dreams, there's a catch to that. As Marco said, using the hash based approach gives you a lot of control in the render cache already in the Drupal 7. But if you now take a look at that example, and if you want to have the content, then you would need to add all the hashes of the main output to the content area. You would need to add all the hashes of the node to the listing and so that gets complicated very fast. Just as an example of like a node with many comments, you already have this problem because it's just a massive work that you have to load all the comments and you have to calculate the hash for all those comments. And so you have to recursive, call down. But you might not even know how many nodes this comment is displaying in advance. So that's a problem. So this is just a real massive work to get it to done because then the comment might have a user picture and anti-reference to something else, but it's again embedding something else. So the comment based approach kind of got to its limits there. And should we just give up the dream? No way. Because Drupal 8 has you covered already in that case, and mostly at least. And that's what we're going to be talking about now. So you guys saw the amazing improvements that this render caching can bring to you in Drupal 7 today. Even with limitations that have been explained, so the hash based approach, you have to pull in all the different bits that the things you're rendering are depending upon, which can become very tricky once you start going to higher levels of things. So for example, a block that contains a view that contains a note contains fields, which contains reference entities, which contain again fields. Obviously that becomes very, very painful, very fast. So the solution to that are cache tags. So I'll explain that a bit. Go over the API and the X. So hopefully show you that it's conceptually very simple to understand. So that addresses really the hash problem that Fabian just explained that could potentially prevent that dream from happening. But in Drupal 8, thanks to cache tags that is actually going to be possible, feasible. Entity render caching in Drupal 8 is enabled by default. I'll cover that as well. The way cache tags are bubbling, uncacheability. What do we do with that? Because some things are inherently uncacheable, so we need a solution for those as well. And then general picture of Drupal 7 versus 8. So I think most of you have seen this page before. And there is only one bit that isn't blurred, which is cache pages for anonymous users. Basically the setting to enable the Drupal 7 page cache. And I think many of you are, or quite a few of you are going to be relying on this today. But I wonder how many of you have already known this. Because this setting works very well, it caches pages for anonymous users. But did you know that if any user posts any comment that every single thing in the page cache is going to be deleted, if any node is created to the entire page cache is deleted? So that is not very efficient, obviously. That's not really what we want because as Fabian was showing in the picture of the dream, we would ideally still be keeping the chunks of the page that are not affected by changes. So really this is clearing the entire page cache on node save. That's not ideal. And that's because the way the cache API in Drupal 7 works and the way it supports invalidation is it doesn't really have anything specific for invalidation. It only supports key cache ID based invalidation. So in Drupal 7 you can do cache invalidation in three ways, essentially. You can clear a specific cache entry by passing in the cache ID that you want to invalidate. So the exact cache ID, you can clear a course set of cache entries and that actually just means you pass in a prefix of a cache ID and then anything that matches that prefix will be invalidated, but that's again not very powerful. And then third and last you can clear all cache entries and this is what the page cache does. So that's obviously not what we want. So the way to address this or the way this is problematic is if we have the question of how to clear all the entries, all the cache entries that contain Node 42, even if it's just a title of Node 42, anything that is rendered, that is cached, that uses anything from Node 42, how do we figure out the cache IDs to be invalidated? The answer is we cannot do that. It's simply impossible and that is where cache tags come in. So a cache tag, so let me go back one slide. This all looks pretty familiar to you guys I think and we have in Drupal 7 the cache underscore set function which has a bunch of parameters. Well basically in Drupal 8 it's the same, but there is one additional parameter at the very end, the cache tags. And cache tags essentially look like this, cache tags are merely strings. So a set of cache tags associated with a cache entry is just an array of strings. It used to be more complex if you saw earlier presentations of mine or if you looked at Drupal 8 code before, it used to be a rather complex nested array with lots of subtleties. Now it is very simple, it's just an array of strings, period. Typically we separate for example a Node 5 as the cache tag Node colon 5. So we use a colon as a typical separator between some sort of domain of things and then the things within that domain. But you can do whatever you want really. So a cache tag is a string and adding a cache tag to a render array is as simple as accessing pound cache which already existed in Drupal 7. There is a new key now called tags and you just append a string to that. In this case we are building the cache tag for user, whatever the user ID is. But because every single entity in Drupal 8 has cache tags already or we use cache tags for them, it is kind of painful to be constructing this string over and over again and imagine if you have a typo in just one little page of your code base and then trying to debug that, that's not going to be fun. So instead of making such a painful DX, we provided a get cache tag method on the entity interface which means that every single entity, no matter whether it's a content entity, so for example users know its terms but also config entities like menus and tours or blocks, all of those have a get cache tag method. So it's always the same way as soon as you have an entity just call get cache tag on that and you have the cache tags that are associated with it. Get cache tag does not return a string as you might expect from the previous slide but it returns an array, array of cache tags because maybe in some cases, and there is one case in Drupal core for example, you might want to have multiple cache tags associated with that thing. So we just leave the door open, you can return one and that's the usual case but you can return multiple if you want. And then if you want to actually use this, again looking at the example of adding a cache tag to a render array, we used to do it with a string that's being appended to an array but now we can actually just call a helper method called merge tags on the cache class and it allows us to give one set of array, one set of cache tags, another set of cache tags, merge them together and assign them. That's all this is doing plus a nice side effect of this is that you can just call the cache tag method on a whole bunch of entities, you just pass in all of them and all of them will be merged together, just like set merging works. So it's very easy to add many cache tags around the array as well. In terms of invalidation, you could do it manually as the bottom example shows, so invalidate tags is the method to call in the cache class and pass in a set of cache tags again, but in general you will never ever need to do this because just invoking the save method on any entity or modifying an entity in the UI, all of that goes through the save method of entities and that already takes care of cache tag invalidation for you. So in general you never ever have to worry about invalidation. In terms of the X and making it not painful unlike some things in Drupal 7, we provide very explicit exceptions, so if you try to pass in anything else on a string, it is going to say, hey, you did pass in a Boolean or an array or something else, you will be notified and you'll be able to spot errors right away. So I told you that it's working automatically for entities, but what does that really mean? So let's take a quick look at, for example, rendering a node. So we load node 5, we build its render array, then we actually render it. So we invoke Drupal render on the dollar build variable. And then if we look at what's in pound cache tags after we've rendered it, we see, for example, filter format basic HTML. So that means whenever any setting in the basic HTML text format is modified, the cache tag is invalidated, which means that the nodes that has this cache tag as you can see is going to be invalidated as well. So any filter format change is going to be reflected immediately. Node 5 is for this entity that we're rendering. Node view is for the view builder. So, for example, if you modify the view mode, so, for example, you show the title field below the body field for some reason, then this makes sure that that changes immediately reflected so that your changes in display modes are immediately present. Taxonomy terms are associated as well. The user, for the user picture, is also associated. So just to give you a concrete example, as you can see, everything bubbles up right from the field level. Quick question. The question is, does it mean that translations are picked up as well immediately? The answer is yes, because, and that is not covered in this part, everything that is rendered cache is also varied per context that it depends upon. And it also has a translation context. And it also checks if there are translations at all. So if there are translations, for example, Node 5, imagine this was translated and there was, for example, an English version and a Dutch version, it would detect that there are multiple versions. If so, it would vary the cached entries. So the English Node 5 and the Dutch Node 5, they would be varied per language and therefore they would have separate cache entries and therefore that would work. Yes. Maybe we should answer that question later on because I think that's a very deep D7 question that I'm not really familiar with. So moving on, entity rendering. So basically automatic rendering of entities is happening. So a question now is how do these, as we saw on this slide, the cache tags associated with fields within a node are bubbled up. They are available. So how does that work? We have bubbling of cache tags just like JavaScript events. I assume that quite a few of you are familiar with events bubbling in JavaScript. So basically from deeper in the tree, bubbles up to higher up in the tree. It's just the same with cache tags. So assume that this is the initial state. So this is kind of a rough representation of a Drupal page. We have the entire HTML page. Then we have regions within the page, blocks within the regions. And then, for example, a view within a block, a node within a block, that sort of thing. And for example, at the very bottom, you can see that there are two fields. There's a node, but the node doesn't have the cache tags for the fields within the node just yet. This is where bubbling comes in. For example, the block that contains the node doesn't know about the node cache tag yet. So the bubbling makes sure that this is what happens. Everything bubbles up. So in this example, if you look at the node, for example, you can see that user two from the user field has already bubbled up. The cache tags for the body field with filter format has bubbled up to the node. And that has bubbled up to the block. And that has bubbled up to the region, which has then bubbled up to the HTML page. And that is really the crucial thing. As Fabian was saying, if you don't have something like bubbling, you will have to manually dig in deep into the tree to figure out the small pieces and bits that you're depending upon to make sure that it's invalidated when necessary. Bubbling takes care of that for you automatically. To visualize this a bit more, I have a small demo here that is hopefully going to be useful in understanding this. I'm going to make this a bit smaller. So this is a Drupal 8 from a few days ago with a few hacks to visualize things. And as you can see right here, there are 21 fragments. So pieces of HTML render arrays that have cache tags associated with them. Seven of them are render cached. And the things with the yellow outlines, those have cache tags. And the things with that's better. The things with the green box shadows that are flowing inwards, those are the things that are render cached. So in this example, you can see that there are cache tags all over the place. So for example, this is a main node that we're displaying and it has a user. It has a taxonomy term. And those have their associated cache tags. But we also have an entity reference, which again renders an entity, a node in this case, which then again contains a user and again contains two taxonomy terms. And all of that bubbles up all the way to the page level. And hopefully this makes it kind of clear how all of that works. It's just that the yellow things are bubbling up to the bigger yellow things or the green things, which are then bubbling up to the page level, which brings us to the final points if I can figure out how this works. Okay, wonderful. And no longer my slide. So everything bubbles up to the page level, which then eventually ends up at the response level. And that's why we in Drupal 8 will have or currently already have the X Drupal cache tags header. And this is the really, really powerful stuff because this allows us to see at a glance which things are contained within the current response, which also means that it is, for example, available for reverse proxies for CDNs. So instead of doing things the old school way, which is if node five has changed and I have things stored on my CDN, for example, news article, and the news article is listed on five different pages according to different categories or something, you have to figure out all the URLs where my node appears because otherwise it will remain there. And I want it to be invalidated immediately because there is a breaking update to that news article, for example. Well, thanks to cache tags, we can now exactly which URLs, because the responses contained this header, you know exactly which URLs contain that piece of content because node five or whatever node it is, we'd be in there. So we can purge per cache tag on reverse proxies like Farnisher or CDN and have instantaneous invalidation. So that's really, really powerful for websites that have anonymous users mostly and then can push everything to the CDN and not have to worry about any incoming hits basically because they can invalidate very, very precisely. And the purge module is already being updated to Drupal 8, is already working with this. So if you want to give it a try and give feedback to Nils Amorek, who is here in the audience as well, feel free to give it a try and provide some feedback to him. So that was all about cache tags and that's the really exciting stuff, but there's also the uncacheable aspects. There are some things that are never going to be cacheable and one painful example of that is, for example, comments, the comment forum in particular. A comment forum in Drupal 8, and I think it works kind of the same way in Drupal 7 as well, but I don't know the exact implementation details there. But in Drupal 8, a comment is just a field on a node, just like any other field, but it's rendered in a particular way. Instead of rendering a thing, it's rendering a list of comments, the comments that have been posted to that node. But the problem is not the listing of comments. The problem is the forum that allows you to create a new comment, because that forum is personalized. For anonymous users, it's allowing you to enter your username, email address, home page, whatever, but for an authenticated user, it is actually immediately personalized, personalized to the current user. It's showing your username and therefore it is something that needs to be cached per user, which is not nice because then that would actually mean we have to render cache every node per user, which then removes pretty much all of the benefit that we had. So what we want to do is still render cache for anonymous users because they always get the same forum, but for authenticated users, we want to not cache it at all. And that's where a new property comes in called post render cache. And as the name suggests, it runs after the render cache. So the way that works, and I'll go over this briefly because it's something that you will only need in advanced cases. And if you can, you should avoid it. It's only in the utmost necessary cases that you should be using this. The only examples in core are comments, node links and comment links, because those are all personalized. So you specify a callback to be called. You specify the context that is needed to generate this dynamic, this hyper dynamic thing. In this case, we need the entity type that the comment is going to be posted on, the entity ID of the entity that it's going to be posted on, and the field name, because there can be multiple common fields in Drupal 8. And given the callback and the context necessary to build this dynamic thing, we generate a placeholder, which is just a bit of HTML. And the placeholder is always going to be unique. So we know that there is only going to be one of this ever on the page, so we can find it reliably in the eventual HTML. So the placeholder that we get, we assign to markup, and we provide the post render cache property. Then in the callback, what we do is we receive the element that is being modified, the element that is being rendered, and we also receive the context that we specified in the previous step. So after render cache has hit, so for example, we receive a node that is fully render cached, but then we also see that there is a render post render cache callback associated with it. We receive the context again. We dynamically build an empty comment, an empty comment object entity, and then we can get a form for that empty comment. We render that form so that we have again just plain HTML, a string, and we regenerate the placeholder so that we know the unique thing to find in our HTML, so we can replace that with the comment form we just rendered. So basically it's generating a placeholder that is unique in the HTML, building something dynamic, finding the placeholder, replacing it with a thing that we built dynamically. As you can see, you'd rather avoid as if possible, but for some use cases, it makes sense. Placeholding in general is a pretty good concept, but as you saw that API is at the moment very low level, there's an issue for a helper class that will make this way easier, that will probably get in. Yep, thanks. And that's most of the things I wanted to cover, just one more bit. 7 versus 8, 7 versus 8. The general perception is that Drupal 8 is slow, and to some extent that is definitely true, but we are at the point in the really cycle where we just an hour ago or so we released beta 1, so we are still optimizing it. Only now lots of the APIs that are internal are really stable, because render caching is something that we could already be working on and that's already been implemented, but lots of the fundamental stuff, the very deep low level stuff, was still too much in flux to be optimizing a lot, so this is the stuff we can optimize now. We can still be optimizing it. So Drupal pages were ships, and Drupal rendering a page is somewhat similar to building a ship, if you will. Lots of things together form a bigger thing. Then this could be Drupal 8, as in a nice understandable ship, nice structure, lots of components and dependencies are clear, but Drupal 7, while it was faster, looked more like this. Like it was talking to a zillion, it was talking to lots of different small pieces, and it would be really hard to understand it completely, how it even rendered a page, but we're getting there. So if this is a well performing Drupal 8, and it's kind of falling off, but it's a full Drupal con in LEGO, then this is not where we are at, but we are more at a place like this, where we already have all the foundations, we have a lot of the great APIs, and we can still optimize internals if we want to. And now Fabian is going to show you really amazing stuff in Drupal 7. I still don't know how he pulled it off, but I can't wait for this to be happening in Drupal 8 as well. So Fabian. I've set out on a mission to build the fastest Drupal ever, ever in history. So what I'm going to present you now is a work in progress view of the 7x2x branch of the Vendor Cache module. Let me just give you a quick overview. The Vendor Cache 7x2x will have cache tags as well, so you can do everything that you can do in Drupal 8. It will completely replace the block cache. It can take over the page cache to some extent already now, the entity cache like in Drupal 7. All it's completely compatible at the moment with the version 1, and it has some pretty cool stuff lined up, because all that what we've seen so far has been within the page. So Drupal is completely bootstrapped, and then we are doing all the Vendor caching. What would be really cool is if you could not only have a page cache for anonymous users, but for example also for authenticated users. How many of you have used OS cache or similar modules? Okay. So Vendor cache tries to achieve that in a much simpler way, because due to cache tags and all those other things, due to granularities, due to bubbling up, which is possible in Drupal 7 with some tricks, it is possible to achieve that goal in a way that we could for example do all that you have to configure manually in the OS cache and where you have to deal with different things, do that automatically using the post render cache with some placeholders. So what would be cool if we had a middle web page cache that's sitting at the first point of Drupal 8, or if we could do everything in hook boot, or even before, and all that we kind of need for that to do is we have to cache a page, but we have to put in a placeholder. For example, we have a page, it has a normal page, but it has one block that's per user. So we can cache all pages normally, but this one block we would need for in Drupal 7 terms Lord via Ajax or do something else, but if we are changing our cache IDs to actually include placeholders for the granularities like person user or person page, what can happen is that we get an OS cache automatically out of the box. Because we get the page from the cache, we expand the CIDs, and then we just do a cache get multiple. If you get a hit, then the user has visited that site again, the block is cached, we just return the page, replacing the placeholders, and if you get a miss, we are just processing the request normally, so it's not even very complicated. Why there's similar technologies like ESI module, etc. You would need to call back into the block system, have very complicated authentication themes. A placeholdering system is allowing you to be very flexible. And the nice thing is, yeah, that works best for would work for logged in users out of the box. The simple granularities work best. I got it working as a proof of concept at least locally. I was very excited when that happened. And you could make it extensible so that you not only have a granularity per user, per role, and what Drupal calls support, but also face of the moon if someone needs that. So, but the nice thing is let's now no longer take a look at what we can do inside Drupal, but let's get outside. Let's take a look what we can even do before PHP, before Apache is even hit. There's memcache plugins for NJNX and Varnish, and that means we can theoretically at least get the page from the cache, replace the placeholders by doing another cache get multiple, and then now that this page, we can directly serve it from Varnish or NJNX, no Drupal hit at all. The only open problem is how do we authenticate the user sessions, and how do we expand the cache IDs, so there would probably at least at the moment still need a custom NJNX or Varnish plugin. There's obviously the standard techniques, ESI, Ajax, and the Ajax on local storage. Yes, local storage. That means we could have a block that's kind of, we retrieve via Ajax, but when we are loading the page and we see we have it in local storage, all we need to do is we need to ensure that the cache tags are still matching of what the remote has, and then we can just take it from the local storage from the JavaScript. How cool is that? The nice thing is we can use the same place-holding system for the outside of Drupal. Now that we have kind of a granular cache ID that's giving us a lot of flexibility, but the only thing is we need to ensure that we indirect this via UID, and that's for security reasons, because you not want someone to just say, like, hey, my cache ID is admin password stored here. No one would store the admin password in cache, but there might be sensible data that someone could get at if you would just allow direct access. So by using UIDs, you're kind of starting tokens for the cache IDs. So now Ajax, as I've already said, always was a little problem, because you would need to know how do I build this block? And the nice thing is if you do the ESI or Ajax and knowledge of the original request, then in a cache get, if you get a hit on that fragment with the expanded cache ID, you would just return the fragment. It's all well. But on the slow pass, you would just execute the pass that is passed in like the Drupal request, and one can get you that automatically, or it can get an authorized pass via Ajax in some way. And then you just execute the page, and then for all the place-holders you get on the page, you just return that one fragment. So the fragment is built in the original way, and that solves a lot of problems, at least for Drupal 7, where you don't have to deal with, well, how do I get to that place-holder now? How do I call this block? How do I call this custom function? Now we have a problem, because we want to cache the fragments, too, especially for ESI. You have like a page, and then you have a little string, which is doing a sub-request to Drupal, and what you really want is for the user block, you've now so carefully devised to come via Varnish, you want to cache that fragment, too. So what we really need is we need an expire-setting, and we need an authorized context. ESI module has that. It uses a lot of cookies. That's one possibility, but there's some other things we can do, too. One of the things I'm proposing for Drupal 8 as in Drupal 7 is kind of a new cache property, which is called a TTL, that also allows to make things like cache synchronization possible, where if you know that object is about to expire in Drupal, you will send to the client, well, this is just about to expire. Please check again in one second. There would be an API addition, so it can happen pretty much any time, but that's something really Drupal still needs in the cache system, besides the granularities that you could bubble up, because having a TTL, instead of just the expires, which is just a low-level cache system, and with some cache backends not even taking into account if that has expired, really, you have a much clearer way of defining it's similar to a Max H header in HTTP. Now if you want to pass a context for Ajax, what we want to need to do is we would put a user ID, and then we need to authorize that with a token. The token could be valid for like 24 hours or something like that. The simplest is just to use the Drupal hashing mechanism, and from the UID plus some timestamp-based thing, you can generate the token, because the nice thing is again, because we have the original request, if the token was not matching, we can just bootstrap Drupal up and give back the right information, because then we can not only validate the context we are in, like the user, but we don't have to rely on the data that's passed in the same for the page. For ESI it looks a little different, so you are looking again at fragment X, but because Varnish does not implement the full ESI spec, you have to actually send that information in the header or in some cookies instead of that, and again would use the same tokens. Now there's a really cool trick you can do that I found and that I prototyped and that I hopefully will put a sample VCL file in the render cache module. You can actually cache the session with and Varnish from the session cookie to custom headers. There's a Varnish return restart, and that means essentially too much to go into the details, but what you get into Varnish is a mapping of the user session to this XDrupal UID, XDrupal roles, whatever context you need internally. There's also someone using that with AusCache or ESI module, but the nicest thing is you can cache it internally, so PHP is never cold and it's just kind of just within Varnish very fastly authenticating the user and that you can do proper ESI with AusRise headers. Another thing that Drupal really should do is Drupal should decide if Varnish should use the ESI or not using like a XDrupal ESI header setting request ESI true, and the same Varnish should provide XDrupal has ESI so that Drupal knows this is a Varnish instance that has ESI and then Drupal can decide on different rendering strategies. Open problems here are what about the assets, what about JavaScript, what about CSS, how to bundle that, how to load after replacing placeholder. If I have a ESI fragment, I've talked with some people, they said ESI module does not solve it. There can be something like adding just assets that we now are not there, and the nice thing is because we always have the original page context in what this was done, we can do a lot more in that, but it's still an open problem. Another thing is form tokens, as Wim already said, form tokens are a big problem, just if you ever try to cache AusRise users in Varnish or Akamai, then you'll probably have hit that problem. Cacheable CSF by net solves that, and this really should be in core that you can replace cacheable CSF token via cookie in JavaScript, at least for non-admin pricing forms. And now we get to something really cool, it's a word premiere. It's really, really cool. Big pipe with Drupal. It's a Facebook idea. It means we show the page as soon as possible, but then we continue loading it, and we stream the content to the client. That's theoretically already possible in 7x. Core is predetermined for it because Drupal is so nice, so flexible, and the only change we need to do is we need to change the page to be an HTML top, an HTML bottom template, and then we just send more data before the closing body tag. And the nice thing is once we receive that data from the placeholder, we are sending the CSS file, but then we can send all the big pipe JavaScript files bundled as one aggregate in the footer. But what we would really need is to not have to kind of send the CSS files at all, but have an intelligent bundler that says, oh, this has been requested several times. Probably this block will always have the CSS file, so just put it into the bunch that we are always loading. In the worst case, we load a little too much. We can also have an intelligent pipe. That means we can return content if the data is cached already in cacheable. Let's say we have a micro block cached for 10 seconds, then we can just return it, and in the other case, fall back to back to pipe so we can still nicely stream real-time data. So, let's get to a demo. This is a page, and it loads really slow, because we have one block that takes two seconds. So, let's not spend too much time on that. I'm going to enable the big pipe module model. Now, you cannot see that it's magic, but when I click now, it's immediately there. So, this is really fast, and then the data is streamed, and if you take a look at the inspect element at the network request, what you are seeing is it takes the same time. So, it's still two seconds, but you've replaced the waiting time that was there before with retrieving time. So, pretty cool, isn't it? How many lines of code do you think this would take to do? Like 100? 1000? No, it's six. And this is how it works. You enable the render cache module with render cache block module, render cache big pipe module, and you're just setting your block that was uncashable before to cache custom, and you're putting a render strategy of big pipe. That's all. And to try that out, you can check out the 7x 2x dev branch of the render cache, and you can check out the demo module I've used for the big pipe, just enable RC site, render cache big pipe, try it out for yourself, and that did five more time for questions. Please speak into the micro for questions. So, there were quite a few, I just wanted to say there were quite a few links in there in various parts of the slides. We'll tweet the slides just after the session so that you can just look at the slides instead of taking photos and then probably not having them be legible, just FYI. Is this on? Yeah. I got a question for Wim. I was supporting a module from 7 to 8 the other day, and in 7 it used to implement hook entity view alter, so on every request it would do something with the entity and then process it. Now, the way I see it, I got two choices now. Either I use the post render cache processor or call back, or I keep using the entity view alter and cache whatever I'm doing there myself in my own cache and keep using that. The first thing is correct, so post render cache, so you have to take into account that entities by default will be cached per language, per role, the typical things, things you would definitely expect, and post render cache always, always runs. So, if you have to do something dynamic, that will always work. But it sounds like what you're doing is kind of dynamic and it depends on something, I don't know what the determining factor is, whether it will be visible or not. Yeah, it should indeed run every time an entity is built or viewed. Okay, but it kind of depends on what it is you're doing exactly because probably you're doing something different depending on some context. Maybe you're varying per country or per currency, that sort of thing. And just taking out one field and using it for something else. So what is the dynamicness about it? If it's something that is the same whenever the entity is viewed, then you don't have to do anything special because it's just going to be consistently cached on. So I thought you were saying this altering that you're doing, it depends on, I don't know, some user setting or something special? No, it does not depend on some user setting. Okay, so then everything remains exactly the same as in 7. If it's cacheable and it is not dynamically changing around depending on some kind of context, then everything is the same. If you want to do something truly dynamic, post-randocache is an answer. But if it's not really dynamic but it's just depending on something else than user role or language, then you could define your own cache context. For example, if you want to, if you're a news website that's writing for both for the Netherlands and for Belgium, you could detect based on the IP address which country the user is from, which is then a new cache context and you could say very per country. And then whatever you do for Belgium would still be render cached per Belgium. And then what you do for the Netherlands would be cached for the Netherlands. So you've got more flexibility there I guess, but the use case you were citing remains exactly the same. Okay, thank you. Any other questions? Hi guys, probably a dumb question. My team was evaluating render cache the other day and what they were saying was we use entity cache anyways. So what's a big benefit of render cache? We don't have any comments. So entity cache is just for the loading of the entities. But as soon as you render, but for loading the entities, that's a node load that's cached. But what render cache is doing, it's caching the node view. If your site is fast with a node view without the render cache, good. But yeah, the other thing is that might have happened is that you did not enable the render cache node module because in Drupal 7, everything uses like node view, comment view, whatever. That's why render cache ships with a lot of helper modules because the problem is render cache really can only do it for things that are calling entity view via the entity module. That's the same at least in 7. That's the same in version 1 and version 2 without hacking core. So what render cache provides is a real big set of modules in the version 2, even for the block cache, that you need to enable so that everything goes through the render cache chain, which is giving you a little more structured boat to speak in WIMS terms. And with the alter hooks gives you control over the caching, which is very granular in that. So probably enable render cache views, enable render cache node and then try again. Sure, sure. One more question. For the 2x version, yes, does it also work with Wanish hash ninja? Wanish what? Hash ninja. So hash ninja is a feature available in Wanish where you can cache tags. And then it's basically a hash of every page. And then you can create a hash based on the different components of each page. So if one component changes, the hash changes. So Wanish knows to clear the cache. So I was thinking cache tags and this works with that as well. The problem is in Wanish, at least to my knowledge, the hash is calculated before the request is sent. So no, this one calculates after as well when the headers are sent from the application. But, well, the 7x 2x version just sends the same xdrupal cache tags so you can do the same as in drupal 8, at least. About entity cache, they actually work really well together. In my benchmarks, when I enable also entity cache for the node benchmark, I get from 14 to 16 pages per second. So that also helps a lot. Probably we didn't enable all the modules as Fabian said. Yeah. Thank you. And just one more bit about cache tags and varnish. I didn't know the exact module you mentioned for varnish. I'm not a varnish expert at all. But we discussed cache tags in drupal 8 with the varnish people, the CTO of varnish software, who was actually doing commercial stuff with varnish and doing very, very big deployments. And they were actually already experimenting with cache tags in the exact same way as well we are supporting already out of the box in drupal 8. They support invalidations easily of 1 million invalidations per second. So all of this cache tags and as Fabian said, render cache 7.x 2.x also exposes this xdrupal cache tags header. So you might want to try using render cache 7.x 2.x with its cache tag header in combination with varnish. It's explicitly supported. Okay. Is there a release plan soon of 2.x? It's open source. So the more you help, the faster it gets released. Thank you. Instead of George will do it, Fabian will do it anyway. Just kidding. We didn't quite catch that. Can you repeat please? No, I was just joking from Madrid's keynote where he said George will do it. So thank you very much. I just wanted to say thanks. This was a really nice session. I guess you know that by the amount of applause you got. I have a question about cache invalidation in drupal 7. And you said that you can only invalidate caches with the prefix. And I've been there. I tried to make a smart cache ID by stuffing some IDs in there. And then I hoped to do some kind of search inside the cache. And then if you go into the cache interface or the cache database implementation, you see that it's just adding in the SQL query the cache ID and then the wild card. So is there a reason for that? Couldn't you just pass in as the cache ID, the query that you want to search? Because that would make it more flexible. You could definitely do that. The real problem that's not doable is because Drupal supports multiple cache backends. So you could have memcache, APC, Redis, whatever. And the Drupal API needs to be as flexible to support all of that. So that is why cache text was generically implemented in Drupal 8. But there's two things you can do. The first thing is what render cache 7.x1.x does. And that is it uses a hash. So you're changing the cache ID always whenever you do something. What render cache 7.x2.x is aiming to do is to get away from the hash so that your database does not fill up and using a technique instead of doing invalidation to do revalidation. That means you store the current context of what your cache ID is in at that point when you are creating your cache set. So let's say you have a note and it's modified in some time or whatever. Then you would use, for example, the entity modified module. You would say entity modified last ID. You would store this last modified time within your cache, like in a special array or whatever. And then whenever you retrieve your cache, you check if your cache is still valid. So cache invalidation is a great possibility to circumvent the problem of a difficult cache invalidation. That's a strategy worth trying out. Thank you. Okay. Hello and thanks for the presentation. Quick question, probably a stupid one. Do you have any hints on, let's say if you have a view that lists newest nodes, how do you invalidate the view if you create a new node? Is there any chances of doing that with the tags? So is this a triple seven or eight question eight? More like an abstract question. Okay. Abstract. We like that. So in the abstract, the most simple implementation possible to do that is also the one we are working on actively right now because indeed that is a problem that needs to be solved. For example, the front page in Drupal 8 is a view that lists article nodes or maybe all nodes I don't even know by heart, but it lists all nodes by newest first. So that's exactly the question you're asking. And the answer to that is we have a listing cache tag. So a cache tag that represents a listing, the listings of a certain entity type. So for example, there is a cache tag called node underscore list. Imagine that that is the case. Whenever any node entity is modified, deleted or created, so whenever anything happens to the set of entities in the system, we invalidate that cash tag. Then the view is tagged with that cash tag, meaning that whenever a node is created, modified or deleted, that cash tag is invalidated and therefore the view is invalidated. So the answer is yes, that works. Yes, that is supported. But making that as granular as possible and therefore as optimal as possible, that is something that we will not be able to fix in Drupal 8.00. But hopefully in a subsequent release of Drupal 8, we will be and it definitely is going to be the case that we will be experimenting with that in Drupal 8.00 contrib because there is different strategies possible. But it is definitely something that is possible. So it definitely is a hard problem. I think I've spent more time talking about the toppings than almost anything else. Listings is really hard. What Drupal 8.00 will provide you, Mark Sonnenbaum promised me that, is an altar hook, which means you will be able to change the listing because you as a programmer now that this listing contains these kinds of entities and then you can, for example, just put a generic cash tag for the entity type or the bundle or whatever because you know what it contains and even if the Drupal detection isn't perfect, you will have a fine-grained control of making it more perfect because it's frequently hard to find out what a view is showing, but it's very easy if you build the site. And that's also what the RenderCache module in 7.0 is about. It tries to give user control over the caching in that. For the 7.0 plans, yes, it's plans to support the listing as well. But what we found is that as soon as you use entity views everywhere, like from views, et cetera, it doesn't even matter as much that the views are not completely cached because what really is slow about the view rendering is not the query, that's the rendering itself. There's also a module called ViewsRowCache that will be soon released on Drupal.org or ViewsCacheRow, one of the two, by Francesco Placelo Plac. Plac, who's the guy behind you? And that will also allow you to render Cache your rows in the view and then only the query is run and then it comes all from the cache. So you don't have to solve all problems in that. Even just RenderCaching nodes has given us on the site so much performance boost on Drupal.org. The second time, page load was so much faster, like Angie was waiting on one thing for like two minutes. And afterwards, it was like 20 seconds. So there's amazing things possible even with the 7x, 1x version. And in Drupal 8, you get so much out of the box. That's another hint for all of you. If you're building a site, put in RenderCache as one of the first things. Because in Drupal 8, it's active by default. Don't turn it off for your staging and production sites and your demo sites. Work with it from the beginning because then you are finding the bugs that are related to caching. Then you are finding the developer that is basing some node based on the page, which is totally incompatible with RenderCaching because it uses data outside of the node. If you start with that first, then you will have much less problems. Then if in the end your site is slow and you're going to some consulting company and saying, my site is slow, we need to introduce RenderCache, we'll have so much more work. If you start with caching, et cetera, in mind and enabled, especially RenderCache, one of the versions in 7 or in 8, leave it enabled, you will have so much more fun. All right. Thank you. Yeah. Why is it wise? Hi. I have a question about really, really, really cool stuff. I was wondering if I understood correctly the big pipe strategy relies on Ajax for rendering slow blocks, right? No. It's not Ajax. It's streamed in the same request, actually. So, if you take a look at the source, we can see it depends on JavaScript. Yes. But here's the end of the request. And then we have like a placeholder. Okay. This is using debug output. So here we go. This is a placeholder. So with this placeholder, this is replaced then by the JavaScript. So the page is loaded as soon as possible. You have the fastest time to first byte as possible. And then the remaining is just putting scripts that are coming one at a time. Let's see if it works. No, it's not. Sometimes Chrome streams it. Sometimes not from the view source mode. Okay. My question was more about whether would it be possible to provide a fallback technique if the device does not support JavaScript or it has not JavaScript enabled? Well, in that case, the point is, and that's what this render strategy that you saw on the slide is about. What I want to do is I want to, and that's something we're talking for Drupal 8 as well, what I want to do is to see, for example, if the server supports ESI, then you would not only put RenderCache big pipe, but you would kind of like a chain like ESI big pipe. If it doesn't support ESI, it would fall back to big pipe. Then you could also detect hash JavaScript. So only the first request is not using it. So if you have the hash JavaScript cookie or some other way your browser supports say set, then you could choose to use big pipe. If it doesn't have it, you would not use those rendering strategies. So that's a nice thing. In the end, it would always fall back to that one thing. And as I said, with the boot placeholder, you could kind of have the, especially if the block is cached, you could have it like on the hook boot and fall back to that method. So there's a lot of possibilities. Thank you.