 Welcome. Can everybody hear me okay? Great. Fantastic. So, we're gonna get one more minute for people to come in from the break and then we're gonna start. And off we go. I hope you all had a wonderful Drupalcon so far and really enjoyed it. Let me know. Yeah, can't do that a little louder. Come on. Okay, and you are all here today to stream your way to success because there's different ways to achieving success and streaming is one of them apparently. So, we're talking today about big pipe, refresh less, ESI, AJAX and more. A big welcome to you just as a beginner beginning a little disclaimer. This is a beginner session. So, if you're not a beginner, you need to leave right now immediately unless you're here for the demos or want to know what crazy things I've been working on now. Then you can obviously stay or for any other reason. So, who am I? I'm Fabian Frans aka Fabian X and by the way if you ever wonder what's that X, first it's a lowercase X, not an uppercase and that originally did stand for Fabian and Linux because I really also want an X extension. I'm at Fabian Frans on Twitter. I work for Techman Consulting as a senior performance engineer technical lead and high performance is really what I rock, what I love what I live. And I recently got appointed to be a Drupal 7 core maintainer, a framework manager to pre-size. So, if you've got any patches in Drupal 7 that haven't seen activity in a long time, now is probably a good time to set them to RTPC if you think they're ready and get them committed because we are going to give Drupal 7 a little renaissance. I was born at the same day as GNU, the free software foundation statement made by Richard Stallman. So, I'm purely living open source history that was found on September 27, 1983. Oh my god, the days today. I wanted to bring a cake but the auditorium was a little too large for that. But I'll have some demos for you later. Just no cake. But enough about me. Who are you? I think I know who you are. Let me get to know you because I know you are all pirates and you're eager to conquer disease of performance. So, who of you won the faster side? Who of you downed? Okay, never mind. 100% if you won the faster side that's really nice. But how do you get one? The answer is 42. No, the answer is ACD. Please don't mix that up with ACDC. That's something completely different. ACD, does anyone remember what that stands for? Maybe in the last line there. I'll tell you it's avoid cash defer. And so you don't get lost today in my session here. You are here. We are dealing today purely with the defer part of it. We'll also get a little bit of cashing but there's other great sessions at the Struppelcon which will deal with the other parts. And just to reiterate that a little more, first of all, if you can avoid doing the work, do so. There's no need to keep your computer running hot if the work you are producing isn't even used. Second, if you can't avoid doing it, cash it. And the third part is if you can't cash it and you can't avoid it, at least don't let your users suffer for it. For example, there's a possibility in Drupal 8 where you have a kernel event's terminate event and if your infrastructure is using PHP, FPM, when we are using that, then you will actually be able to do work after the request has been finished, after it all has been sent to the user already. Similar to how BigPipe does things. Just you won't be able to communicate with the user anymore. That's the different part from the streaming. But for example, if you need to do complex operations and caches that you need to re-validate, you could explore the strategy of just giving the user outdated data, if that's possible from your business model. And then at the end of the request when everything is finished, regenerate that cash and so you're always getting fast responses. But why would you defer? You might know that little problem and you probably all had that already. You have built this huge social network and it really doesn't matter what it's called and you have all this very complex content there in the social network. It works really great. It's tailored perfectly to user's needs. And there's just this one little problem you have, this very, very little problem. It's really not a big deal overall. You say it takes 3.5 seconds to load. That are 3,500 milliseconds. And well, maybe that is a big deal. Maybe that even is a deal breaker and maybe users are even leaving your site for it. So what do you do about that? You need a wonder. A perfect wonder and it needs to be a fast wonder. So you transform yourself into Gandalf. Other magicians had not been available at the time of the making of this presentation, just as disclaimer and smoke a pipe. Just so you know, smoking is not endorsed in any way. It's purely lost for the comical purposes here. And well, that's not a pipe. That's a pipe leaf where you can make some wonderful things out of Hobbit land. And you smoke a big pipe and you think, what if I cheat? What if I give the user the impression that the site is really loading fast, even though in reality it's not? And that is perceived performance. And this perceived performance is so much more important than actually what your server is doing. For this user it just matters when you can start interacting with your site and when you can start seeing your site. Because he might be on Google, might have found some content. Now he clicks and has to wait and wait close to the window. But if the user is seeing anything, even just sometimes like a loading or any feedback, then the user knows, wow, that site is alive. I'll get my content in a moment. So they'll be less likely to leave. Perceived performance by now is that important that WebTest base, some of you probably have used the WebTest is doing a full survey maybe you've taken it, maybe not, if not you could, where you get A, B testing and you have to choose which site you perceive loading faster. So there's a whole science around that now. And that's why it's so important. And that's exactly what Facebook does since ages and linked in since a while. They are cheating. Actually with Facebook you have an option to turn their big pipe technology off and I'm kidding you not, it takes those 3.5 seconds. So it's not that our complex systems are slow. It's not that they are not nicely built. It is that complex sites take time. That it takes time to deliver this value to your users. And that is why you can use perceived performance to do that. And that's what Drupal 8 out of the box can now do too. In 8.1.0 big pipe and at core as an experimental module. And in 8.2.0 it will be beta stability. So we even thought about making it stable already. So now really is the time to try it out and I'll just grab a coffee here where you all get out your laptops and are probably just busy trying the big pipe out right now. No? Okay. You want, no? That's not enough. Okay, let's continue. What is streaming? Streaming is available since HTTP 1.1 was released in June 1999. It's pretty simple you send a content encoding of this is chunked content then you send a transfer coding of chunk that's usually what web servers and PHP and all those are all doing automatically. You don't have to deal with anything like that. So it's available since a long time but now almost all proxy supported. And streaming is very simple. That's a streamed response. You just use a PHP script say hello. You flush that, putting it out. Then you sleep for a while where normally you would do your complex operations and then you just say world. And that's it. Hello my world. So this previous PHP script is something I actually use because this is the easiest way to check this is the easiest way to check to see if your site is actually ready for streaming. If your infrastructure, your stack, if everything supports it. Because you might be using something else and you don't know where's the problem is it my streaming, is it something else. No this is the script to use. Your stack needs to be ready. So how can you see that you are streaming a response? That's pretty simple to see. You are using the, for example, Chrome developer tools and you're taking a look at the request there. And when you then go on the request tab on the actual, for example index PHP or test PHP, whatever you call it and then you go to the details of that thing then you see three values. When the request was sent the waiting, the time to first byte, which is so important because before the browser is not getting the first byte it can't do anything. At least with HTTP 1 with HTTP 2 there might be other things but we'll see how the graphs then change in that but as long as the browser doesn't have received anything from the server it can't do anything it can just wait, wait, wait, wait and then the response comes and then the browser can start up to get up the CSS, get up the JavaScript get the images and all of that. But what we are doing here and this is what it means we are ready for streaming is we have a very, very fast time to first byte 0.94 milliseconds and that's obviously just locally and then we have a long content download. So if you see a long blue bar and a little green bar then you are ready but if it looks like this then you are not ready because that means the browser needs to wait 12 seconds or 10 seconds for that script to come back and the browser needs to can't do anything in that and then there's a short content download of 1 millisecond so that is how you can determine that and that's important what is streaming in a more advanced example you might have your infrastructure and you use nginx for example and nginx supports one flag which is called xxel buffering and you just can tell ngin and x that it shouldn't buffer the things you have streaming. So the other header and we are trying to standardize that across different implementations that we've integrated in Drupal 8 is a server-grade control we're sending a control to for example a varnish system which is a store where you can cache things if you're not aware of that that is and then you can tell the varnish that this is a big pipe response and it shouldn't store it and the content is actually a streamed response and with that you can make your infrastructure ready for streaming when the server says hey now a streamed response is coming but not otherwise and that's pretty good because that makes your infrastructure tuning easier because the server needs to know it uses streaming so there's some more configuration needed so the server requirements are pretty simple for streaming there's a way more extensive documentation page for a lamp system it works out of the box so if you're just having Linux Apache MySQL with modphp no problem just works with nginx thanks to that header flag we just send it works out of the box. For varnish you need three lines of code that I didn't put in here because they're already in the extensive documentation for big pipe on drupal.org and it also works out of the box just one example of a CDN that supports it because they already have the streaming available always so now that our server is ready let's get our code ready too let's take a look at how we can do streaming in drupal 7 and 8 and as this is a beginner session we are going to take a look at the groundwork not the highly complex systems we are getting to that later but we are looking at it how we would be doing it now if we were to do everything manually. In drupal 8 you would just use the streamed response and then from your controller you would return your new streamed response with a function and you might know that PHP script inside of the anonymous function there that is just our PHP script that we've used for testing before so there's a streamed response it's not very powerful but it works for simple cases in drupal 7 it's a little bit more complicated because in your hook menu where you define a root for your streamed response like my big pipe stream or whatever you want to call it you have to set a delivery callback because a delivery callback will mean that first your menu is called and once your menu controller returns and in this case I'm again returning just a closure function and then in the callback of the delivery callback I call that function so that's possible too. As you can see the concept is always the same we're having like some dynamic data we are creating in this case an anonymous closure and then in the callback we finally send that out and because now we have control over the output buffer we can actually flush some data the next part flush some data the next part and that's kind of how my prototype in drupal 7 for a big pipe worked I've taken the response I was getting from drupal and I was splitting it at the body tag or a special big pipe tag and then I was taking that, sending the first thing, flushing and then sending the rest of the placeholders which was at the time just some JavaScript so that's so easy because not really complex example why has no one used that before as I said the technology is available since 1999 but there's no real usage of that the reason is pretty simple it's not practical because usually you don't want to just send some hello world that makes for great tech demos if you make it up but you have the very practical business need that the site looks the same as without that streaming and for the user nothing changes it should be exactly the same experience except that it's faster of course so the question is what do you want to stream you could stream nothing that's a default that doesn't have you could stream everything but then it would be a page that would be just empty at the beginning and then there would be some content there and a site bar appearing a menu there and it would get very jumpy that's probably also not a good idea what about every block that could also work but it would mean your whole site bar would be completely empty at the start what about specially configured blocks that would definitely work and I know that David Garcia has made a prototype he's yet to release on Drupal log unfortunately to just configure a big pipe like functionality in Drupal 7 on a block and then you can configure that per block that's really nice but what do you do if it's not a block because while in Drupal 8 we also have as our primary use case at the moment blocks there's nothing stopping you from taking any entity and putting this in some dynamic content which you stream and we'll take a look at how we're doing that later the solution is we want to stream just the dynamic parts of the page and as it happens those are usually also the uncashable parts of the page or which are way too granular for caching because if you say like you have a page and you have a shopping card then you really don't want to cache that page again and again and again for all different shopping cards for all different users that's not what you want so those are candidates for caching for streaming now the question is how do you identify those dynamic parts so how do you find the dynamic part and the idea is pretty simple you placeholder it you placeholder everything that is too dynamic and you also allow the code that you can specify that this can be independently rendered that you give the system information that it can make smart choices for you so that you don't have to configure anything the thing is in Drupal 7 it worked always like that you were going into this panel then you were going there into the configuration then you were clicking there you were looking at that part then you were configuring that cache plugin like that but because that cache plugin is three levels deep you now have to configure a three chain invalidation exploration root but because there is some specialty you have to configure something else but that thing lives in a view which again needs some different caching rules and you can see it gets very complicated very fast and that's the reality of many sites that either you say oh I don't care cache that for six hours and we are done and the editors then have the experience of well I know my content well up here in six hours it's less than ideal but it works or you are setting up these complex systems and Drupal 8 is doing a different approach it's not doing the top down approach where you configure everything and it maintains burden we flipped it around now you as developers or non-developers or if you are not a developer you are lucky in that regard now the developers have the burden of defining everything for them so that the developer says this is user cacheable this is cacheable per page this is like that all the items that are on the page as everything declares itself we have full knowledge and you don't have to configure anything it works out as a box and that's kind of how it works graphically so you have a shopping cart it has said I need to be definitely be per user or even per user session because the shopping cart should never be what my shopping cart is accidentally and then there is a different block and you put a placeholder and by putting a placeholder you are making all of that possible and to make a placeholder you just put in an attached placeholder and render array and Drupal 8 makes this very easy you have cache text, cache context and MaxH this is not a session for it but we are simple Drupal 8 now is for everything how to invalidate it what to vary it on and how long to cache it though things that are uncacheable will say MaxH 0 I am never cacheable not at all don't do that things that are too granular say I have a cache context of user for example and that's exactly what Drupal 8 does it has rules in the services YML where you can define the configuration of what your most granular cache context are like if you want to if you have something else what you are varying on like a custom cache context and you know it's very frequently and you never want to cache that you can say put a placeholder or another example which is pretty cool you have a news site and you have an article and you have a sidebar and in the sidebar you have something which always needs to show the most current news no exceptions never ever what you are doing is you are defining a tag for that block like say it's a news block then there is some tag for it config column block and in that config column block you can define that it should automatically placeholder whenever it encounters that tag so you don't have to configure anything except in this case the configuration you want to have that's a little top down but it's globally managed and Drupal then figures out how to placeholder it's where to put it and in the end it's rendered and it's always count and now we can automatically placeholder it so that's the bottom up approach I already talked about and what makes all of that possible is lazy builders because lazy builders give us the guarantee that they are independently renderable and have no outside dependencies they also give us a guarantee of not being difficult to store because what happened before was we had pre-render cache pattern so when you want to cache something you put in a render array a pre-render function and a cache the problem is with pre-render you could put in a whole object like a node now you could of course take that serializer to disk but that node might have another entity which is a user and an image and something else and you would store all of that and that's not practical because in the end the un-serialization of that would take more time than to build it in the first place so lazy builders really say that they don't have outside dependencies so if you want to auto placeholder dynamic content that's pretty simple you just put a lazy builder and you say the cache is maxH0 something important here that's not on the slides but for you as a secret you don't have to specify the maxH0 here we automatically determine that if that lazy builder was not cacheable we will now and we will then create a placeholder after the fact so even if there's something deep buried somewhere in the system that's un-cacheable the next lazy builder that it encounters will make it a placeholder the other thing is you can directly force a placeholder you set up your lazy builder here for a node 1 and you say create placeholder true an edge case but one we had in core that's why I'm putting it here is you want to force a placeholder always that means you define your lazy builder like usual and then you directly put in an attached placeholders and I've used my unique placeholder in just little brackets as my ID and there's my markup I've added some diffs just for more decay pleasure and obviously you need to be careful if you do something like hello as a placeholder then you can replace everything that has hello on that page so please don't use words that could appear in your content there's a placeholder generator which you can inject into your servers if you really need to usually you don't have to force a placeholder I'm just giving you the opportunities it's possible it's a simple content it lives in attached you can do anything with that you can even inspect that change it but it's for more advanced use case the last thing is what if you have a lazy builder with dependencies and that block needs to show or your custom code needs to show something that determines on the current node then you can actually inject that node into it so it would not be that the lazy builder would be calling out which route currently is active that's calling out into global state that's something we don't want but instead what you wouldn't do is you want to say hey this render array I've taken a look at the root and I'm gotten the node so now my render array is varying by this root so I'm having to set a cache context of root and it's very important that this is a child item you're actually putting the lazy builder like you can call it lazy builder or whatever the key doesn't matter it just needs to be at a different level because now this lazy builder has the node inserted into it it will always render node 1 and will always be the same placeholder that's created for that and that's a little misunderstanding we even had in core it was very hard to get to understand what is coming from the outside and what's getting into the inside so if you don't understand that fully no problem it was really hard and core developers also struggled with it so we have all of that now and it's still not fast and your boss comes and says hey we made the infrastructure and all those changes and I've had my engineers working for a week to change everything to engine X and still not fast and now it's streaming and yeah not so good so now we split our 3.5 seconds up we have 2 seconds for our content load and 1.5 seconds for the stream placeholders so our performance our UX is now down to at least 2 seconds but why is that and the reason is that Drupal still needs to build the whole side it builds everything except the placeholders because the reason is we are not caching anything yet but the remainder is actually perfectly cacheable because we've now taken all the dynamics all the placeholders everything that is there everything that has made our page uncacheable it's all no longer there there's just placeholders because there's no dynamic parts anymore in Drupal 8 we just end the dynamic page cache which is authenticated user caching out of the box in every Drupal 8 site no more dealing with outcache no more dealing with complex configuration no more dealing with roots it's enabled out of the box so on this page maybe we inherited it from the Drupal 8 beta phase but it was not yet enabled we enabled it and like magic it was only 35 milliseconds and then 1.5 seconds of streaming so let's take a look at a big pipe demo there's personalized slow cacheable content and there's personalized slow and uncacheable content because what you're currently listening to is not and then there's a comment form that's also just for you as a user and now take a look there's traditional with this big pipe and wow how are we still waiting and that was with cold caches ok and there was the same total time there but now with warm caches and again big pipe wins it's just there and now you can see the block is coming and what you are listening to so that's so important that actually you're dealing with same thing there and big pipe allows you here to just see those blocks appearing afterwards let me show you that quickly again if we can here that's not yet there now big pipe is coming the first block that's slow uncacheable and after a while then it comes and that's important because for the user it doesn't matter if they're what they're listening comes a little later but for the user does matter that he can immediately see something so if you want to perceive I had another demo but we don't have time for that if you want to perceive past site in troupel 8 you just enable the big pipe experimental module and you're done maybe you need to declare your custom dynamic parts but that's it so let's say practical example you're having an entity and entities are not lazy builderable at the moment I made an experimental core patch it worked but it's not in core so within your entity you're having like let's say the current time and you really want to show that current time or what the user is listening to so all you do is within your entity building within your callback of the view when you're returning your render array you don't call the function directly but you put it in a lazy builder and you put the note in as spoken the entity you are viewing and then like magic troupel 8 will see oh there's a lazy builder I can placeholder that it will placeholder it and automatically you will have a placeholder and your entity and your whole page will be cached without that but then at the end of the page request it will put it in and that's how it works and then you enable big pipe and then your page will load completely and then there will be a little free space maybe you need to style it a little but you can do that because it's your custom code and it will appear and I heard a story from Dries there was once upon a time a site that had common problems and they enabled big problems and problems have just gone away so it works. Ways of streaming the idea of placeholders is not new Larry likes to say everything that is old is new again what is new here is the idea of auto place ordering this because another way to do that is ESI and that's very simple you just put a tag there and again that has been a long time but again it was not that really practical to do because there have been challenges, custom code, many did it but it was not something you could enable working out of the box but ESI is easy now too. Thanks to lazy builders and placeholders you just define a new ESI placeholder strategy, hash to placeholders in the database, define a root ESI fragment hash and you're done. Or for Ajax you put the placeholders into settings and use javascript to replace placeholders. So all of that you can combine you could have something that allowed a big pipe, some say Ajax, some that are ESI but there's one big difference of Ajax and ESI and big pipe. For ESI and Ajax you have any request with any bootstrap and I've just recently seen a site that was using AusCache and it was doing 11 requests on every page load that can really kill your site performance and with big pipe you have one request, you have several inline responses and it's way better for cold cache performance. So be creative and combine write your own render strategies write your own placeholder strategies or let your developer write them. Future outlook, there's ESI big pipe response from the edge CDN and then stream the rest later. So your user gets literally like a 2 millisecond or 5 millisecond response time related to how fast he is to the CDN. Unfortunately, support in fastly is just soon I heard the patch is ready. It was written last Drupalcon by a developer that was there but it's not yet in production. So I unfortunately can't show. And in Varnish I've made a patch for version 3 available which can be found on my GitHub lines. But they didn't accept it and version 4 was so far too complicated to get that in. I still hope to work with them a little to get that in because while currently the page itself can be streamed and ESI fragment cannot. What about Drupal 7? Unfortunately for Drupal 7 there's just prototype implementations and the one by David Garcia is as far as I know still not up on Drupal.org. But there's major work on core itself for me. So get out your laptops, phones, whatever I all want you to open up this note 2, 7, 5, 4, 2, 4, 5. Isn't that awesome? And review my patch right now. Because with reviews we can get that in. Because what this patch does, it does attachments collectors. It solves the Drupal RJS problem of global state. And what it will enable is that we have all the bubbling of Drupal 8 where we can ensure that never any data gets lost is in Drupal 7 as well. The concept is very simple. You just have a subscriber pattern and for anything that's storing something in global state we are putting it instead to everyone that's listening to currently global state changes. And with that you just create your new Drupal attachments collector you get the attachments and you're done. And with that for example, if you try out the patch block cache you enable it all assets you get. Render cache it just works. Early rendering no problems. Render cache the module I just had a site I want to have render cache for some common stuff there. And then it had custom code Drupal 8.js. Contrib code Drupal 8.js. And I could have patched that all and changed everything but it just put in my core patch boom, immediately worked. So it solves this real problem and one very old issue with the block cache. But this is something that really needs to be fixed in core. Because views tried, panels tried, I tried also hard and it's just not possible. If you try to do it without core support you're going to have a lot of attacks but you won't get it right. And that's very, very important base work. Because I need your help. Your help, your help, your help and your help. Because together we can bring back the important parts of the Drupal 8 caching system Drupal 7 including big part. You might ask yourself how you can help. You can either contact or you can come to Sprint on Friday or you could sponsor me for some work as a grant like Drupal 8 that was very successful. Developers were getting grants and working on critical issues. And that did get a lot done. For example, now I'm getting a grant by the Drupal Association to make our testing system faster which will hopefully help everyone. And that's one possibility. But developers that are still using Drupal 7 will be stuck with Drupal 7 for a while and once some more nice caching system and big pipe and everything come to me. Please a round of applause also for Wimlius and Akia who sponsored the big pipe work on Drupal 8 and parts of the Drupal 8 caching system. Thank you. The session test is called RefreshLess. So we are doing that. RefreshLess has nothing directly to do with streaming but it's based on our Drupal 8 caching but you see it's very things. And now with TurboLinks which is now called RefreshLess you see it's very seamless transition and there's no more problems in that. So you can have an app-like experience with the experimental RefreshLess module and you will have nice time. It is streaming related however because it's actually possible to also stream JSON responses. You just have to use a dot progress event of JavaScript. And that's it. Any questions? Thank you. The question was if I could elaborate on JavaScript events since DOM ready isn't DOM ready anymore. And that's perfectly right. I tried first to fake the DOM ready event which didn't quite work but fortunately we designed that in Drupal 8 we won't be dealing with DOM ready. So if you want to do something which you would have normally done in DOM ready you're doing it in behavior attachment. Your site will behave like if it was loaded and then you were able to do some or whatever Ajax requests. So you will get in Drupal attached behaviors on the whole document once the initial part has been sent so the page can then be completely ready and then for every place holder replaced you get another attached behavior just for that part in the context. Does that answer the question? Cool. Yep. There we are. Any questions? Yes. Just one request, it's just longer. Exactly. More questions? Ah, there. Yes. There has been a lot of work to reduce bootstrap but especially in Drupal 8 there's a lot of class loading going on and you can't really cache that in a way. There's routing going on, container loading, it all takes time. So we already tried to send back as soon as possible the response and I'm actually working on a faster page cache which would live in a pre-kernel middleware which is bootstrap container possible so at least for page cache you could have fast responses and probably also for some of the easier lazy builders. But overall it's very, very difficult to reduce the bootstrap and make it faster just from the object-oriented overhead. The full bootstrap in my example had been the 35 milliseconds. That's around what our bootstrap takes 70 milliseconds to 35 milliseconds depending of if you are if you are not yet using PHP 7 please look into it both for Drupal 7 and 8 Drupal 8 completely fully supports it it's well worth it so much faster in Drupal 7 with the exception of one sorting issue we are also kind of ready to say Drupal 7 is ready for PHP 7. More questions please. Seems there's no more questions so I'm doing one more thing if you want to try out the caching it didn't fit in reading the session anymore unfortunately if you have any questions or comments please check out RenderVis RenderVis is a project with which you can use a JavaScript console to actually see what varies on what. Let me see maybe I can get a browser up so with RenderVis you can actually see how the site is performing how the site is what is cached, what is uncacheable what does MaxH0 so that's something to also try out maybe I can show the video let me see so with RenderVis what you can see is you see in the JavaScript console at the bottom you see all your cache contacts that are on the site once you look at it you can put into the JavaScript console a command RenderVis you can say I want to see everything that MaxH0 and then it will visually show you what is uncacheable on that site you can also focus in on the matched elements so you can see that and see the grandparent for that there is a cache context what your site is varying on and I recently used that myself because I was on the site and I couldn't figure out why something was not there so I took a look which cache contacts are there and then I could find out where that was actually happening that was not like that so that's a great tool where you can really see how your site is working it's not that user-friendly right now but if you can improve it a little more I think it could get to be an indispensable tool for debugging cacheability in Drupal 8 yes, we just applied the critical code patch and Wim just on my request released 0alpha1 okay, if there are some more questions thank you very much, have a great day, have a great DrupalCon and if you want to see more of me and like high-performance to Morrow at 215 in Druid Room there will be a 4x high-performance step-by-step one of my all-time favorite sessions and should be fun, that was a backup replacement for another session but the topic is very similar so thank you