 Hi, everyone. My name is Malta, and I'm the tech lead for the AMP project for Google. Tech lead means that I managed the team that works full time on the AMP open source project for Google. And I also wrote some of the code, I guess, which is important because we want to dive into how AMP works today and how it achieves its speed. So even if AMP might not be for you because you're working on an online banking app or whatever, you can still take advantage of the techniques that we use and make your own thing way faster than it might be right now. So I said AMP. It stands for accelerated mobile pages, which is kind of stupid, and I'm never going to say again, but now you know what it means. And it's really all about super fast content on the web. Now, AMP is an open source project, and it's launched inside Google in our search engine, which most of you probably use every so often. And we have this carousel, and here it just boom goes up. So load times are way, way, way faster than we see on a normal web. And you can swipe between results, which is also not something that you can do with an everyday web page. So that's AMP. You can go to your browser, search for something newsy, and you should see these AMP results. So AMP's pretty fast, but we haven't talked that much about how fast it is. And we frankly didn't know. It was an experiment, but it's been out there for a while now, and this is what we're seeing across all traffic where Google Search is leading to AMP results. And so the median load time is under one second. The exact number is actually 711, so it's pretty substantially under one second, which if you've heard about rail time, that's really where you want to be. But one important part of performance optimization is that you can only look at your median user. That's important because 50% have an even better experience, but 50% are worse. So what we typically do is we look at the 90% percentile, so that are your users that have a really bad internet connection loading the biggest web page. And so for them, we're still seeing load times faster than eight seconds, which might seem slow, and I find slow, and I'm not happy with. But if you look at the control group of similar pages that are not AMP, they have an average load time of 22 seconds. So the 1% worst AMP loads are still much better than the average non-AMP loads, which I think is pretty exciting. And all of this, like the one second that we see at the median, is obviously not instant. But through a technique that I'm going to explain today called pre-rendering, you go from fast to instant. The number that we mentioned yesterday is that there's quite some momentum around AMP. And so looking at Google Search Index, there's the crazy number of 125 million and growing every day. And obviously, this could be like only Wikipedia, but what I find more exciting and actually pretty humbling is that there's apparently 640,000 web pages already different domains who in some form another implemented AMP, which I think is really, really cool. And as I alluded to earlier, it's an open source project, and we are shipping new releases every week. Very recently, we finally supported menus, which I agree, as everyone else, is kind of an important feature. We're currently working on forms, and we're supporting all kinds of features like the pretty advanced client-side templating. Now on the next slide, this is actually my favorite analogy about AMP, is looking at this like auto race, there's the average mobile site. And it's kind of in the back. It's definitely not winning. And what I find important to emphasize is that if you're hand-tuning your site, you are going to win this race. AMP is not about winning this race, but AMP is about being up there in front. And more importantly, all AMP pages are pretty uniformly up there in front. And I think if there's any secret sauce to how this works, is probably my answer is going to be the AMP validator. That's MK. He's on my team. It's not actually the AMP validator, but this is how this really looks. So you can go to every AMP page and add hash development equals one to the URL. And then you will get these error messages, or hopefully none. But they're just like compiler errors. And because we're developers and we're used to this, like for us it's just like a to-do list. And we're like, oh cool, I'm just going to fix them. That's awesome. The other effect this has, and I might just speak from personal opinion, that sometimes you might have some disagreements about what the right thing to do is. And so in this case, the AMP validator can just come in and say, no, that's not a good idea. Cool. So going from these basic stuff, let's go into how AMP works. So obviously, we developed this radically new rendering engine for documents, which no, we did not. Because why would you? I think it's amazing we're in 2016, and there are all these browsers, and they're all great. And looking back 10 years, that was not the case. So I think we're excited at times for web development, where you don't really have to worry about browsers anymore. And so AMP, they're just web pages. They don't have a special rendering engine. They're just web pages. And that is why everything that AMP is doing internally to gain its performance is basically equally explicable to all non-AMP web pages. Diving into what's going on there, I want to first talk about front-loading, or rather, front-loading. And I have to tell you a secret. And I hope my friends on the Chrome team aren't mad about me, but here it is. Browsers really hate web fonts. By the way, this is my son, and he's extremely unimpressed with the web in general. You'll see him throughout this presentation. So here's what's going on. That's why I'm saying they hate web fonts. So apparently developers sometimes put front-face annotations in their CSS that they don't really use on their page. So browsers are really careful about downloading fonts. In fact, what they do is they look at your CSS, and then they look at all the other CSS, and then they look at all your JavaScript, and then they apply the styles to the page. And at the very moment where they could have rendered the page, they go, OK, I'm going to go to the network and fetch the font. And Chrome, Firefox, and Edge will wait three seconds for the font. Safari, for example, will wait forever. And so the font is entirely in the critical path of rendering your page. So getting that optimized is extremely critical for good web performance. Summarizing all your style sheets and all your synchronous scripts that are in the head block font download. In code, that means if you have link rel style sheet or you have a script source, those will slow down fonts from even being started to put on the network. Now AMP has certain rules about how it likes HTML to look. And for this reason, what we say is you can have style sheets, but they have to be in line in the style tag. And yes, there can be script tags, but they do need to have the async attribute, which then takes it out of the critical path and browser will happily try to render the page and download the fonts. And the result of that is that AMP can, obviously, having downloaded the document, which is kind of important for rendering it, initiate the HTTP request for those fonts with zero HTTP request in the critical path, which is a big improvement for performance. So there's a problem, though. And that is why this slide exists. This slide is actually trimmed down. It looks much, much worse in reality, because there's window prefixes going on. But so every AMP document contains this bit of boilerplate. And while I think it's a pretty cool technique, it has some problems. So what's going on? Because all the script tags have the async attribute, but some of them are actually needed to render the page, you would get an incomplete render early in the lifecycle, which looks not very good. And so one common technique to avoid that is to manually hide the page by saying, for example, visibility hidden. And then when the script loads, say, OK, now it's visible. So while that works, it has one important downside. If, for example, your network fails at that millisecond and that script never downloads, it could happen that the page stays completely blank, because it says you should be blank. And that's why I think this is such a brilliant idea, which came from some person commenting on a GitHub issue, why don't you use a CSS animation as a timeout mechanism? So what's going on here is that AMP will go, and after eight seconds, show the page if the JavaScript has failed to load. So typically, the JavaScript, as we see, is much, much faster and actually very likely to be in cache. So you would never reach that eight seconds. But it's very important that you have this extra robustness where the page will eventually show if there's no JavaScript. Great. So with that, I want to talk about my favorite topic, which is static but responsive layout. So for this, I'm going to show you a little video, and I'm just going to ask you to read the text. So when I was first thinking about AMP, I had this one idea that this is really the worst thing on the internet. And if I would do anything at all in AMP, I would make it so that this would just never, ever happen. And now I'm going to explain to you why it can't happen. And it's, again, pretty simple. So in AMP, every single element has to have its size defined in the markup. And it's much easier to see what that means in code. So in AMP, you use this web component called amp-image to load images. And while on a normal image tag, you can leave out the widths and height, it's mandatory on this web component. So what will happen in a browser is when it has an image tag and there's no widths and height on it, it will say, hmm, it's probably 0 pixel high. And then it will go to the network, fetch it, and it comes back, oh, it's not 0 pixel high because why would an image be 0 pixel high? And then everything moves down. And so with mandatory width and height, a browser can put a box and then fill it in when it's time to have the image back from the network. Now, with this requirement to put the widths and height in the source code, you might ask, how does this work together with responsive design? And I really want to emphasize that AMP is from the ground up designed with responsive design in mind. So here's the answer. And that's actually a great example of how web components can be really, really nice in web development. So all you do is you put layout equals responsive on the element. And what AMP will then do, it will say, thank you for the width and height. I'm going to use that to calculate the aspect ratio. And I'm going to size the image to the available space horizontally and make the height based on that aspect ratio. So coming from this, there are those situations where you can't predict the size. And again, this is also a nice example of the collaboration on the open source project where I initially was like, you are the luck. You can't do anything. And then publishers were, well, sometimes we do kind of need to resize things. And so we gave in and came up with, I think, a pretty good model to make it work nonetheless. So when AMP thinks about a page, it considers things based on where they are relative to the position of the viewport. So the viewport is what you currently see. So there's the stuff in viewport. And if you already scroll down, some stuff's above. And there's always probably, if a page is longer than a viewport, there's going to be something below. And so if something's below the viewport, and it says, I would like to be a bit bigger than originally planned, then AMP says, that's cool, because that can't really affect what's in the viewport. Similarly, but slightly more nifty, if it's above the viewport, you can still allow resizing because you know how the height changed. You can just subtract that from scroll top, and you end up having everything that's in viewport staying at the exact same spot as before. But finally, we come to stuff that's currently in viewport. And there, AMP is, again, pretty opinion, and it says, you cannot resize it. That is until the user actually interacted with that element. So what you can do, for example, if you need to resize, AMP will just say, no, but you can show a little button to say, allow resize. And then AMP will say, user agreed, that's fine. And then from that moment on, that thing can change its size however it wants. Great, so from that, I want to talk about the next topic. So AMP is designed in a modular fashion, so basically, it knows very little about how to do anything. I can load images and simple videos and text, obviously, but that's about it. And for everything else, there's extensions, which are just web components you load. You think about tweets, Instagrams, YouTube videos, all kinds of stuff. There's dozens of them. And so to load them, you put the script tag on your page. And again, it has the async attribute so that it doesn't block the page. And then you put this, in this case, AMP-YouTube tag on your page. It has the width and height, which is pretty predictable for a video, typically, and then the video ID. But the thing with web components is when the browser sees a custom element, like AMP-YouTube, and it hasn't actually learned what it means, it will go, hmm, let's draw it like a span. I don't know what width and height means. Let's make an inline element. And that is not the best default. And it leads to the same kind of effect of the page jumping around. And it's so bad that there's even a name for it. So it's the flash of unstyled web components. And there's several ways how to work around it. The easiest way is to just wait for the extensions to load. That would actually be similar to the technique we're using to wait for the main script to load, which is the visibility hidden and visible thing that I explained. But we wanted to do better, because some more complex pages might have like 10 extensions. And now you have the HTTP request that have to actually finish for something to be shown. They pile up. So instead, AMP can render the page before all extensions are loaded. And here's how it works. So the core AMP JavaScript library, the one that is blocking page layout, it knows how to layout elements, even though it has no idea what a YouTube video is. So it goes and says, OK, I actually know what width and height means. I know what layout responsive means. I know what layout fixed height means. There's several of them. And it will draw a box. It's not actually gray by default, but it can make it gray in CSS, obviously. And then eventually, that YouTube extension downloads. And then that YouTube extension will say, and fill in that box. And that is a load behavior that we're all used to, because that's how images, for example, usually load on the web. And I think people really perceive it as a decent experience. So to summarize, in AMP, the extension sizing is independent from their implementation. So you don't have to know what YouTube is to make a box for YouTube video. The extension are loaded with an async script, so they don't block anything. Their boxes reserved immediately. And then they're filled with content with the extension loads. All right, coming from this pretty AMP-specific thing, I want to come to a topic that is really applicable to every single web app out there. And that is DOM mutation batching. So there's a simple rule that everyone should follow, which is that you should not interleave reading and writing to the DOM. Unfortunately, it's actually really hard to do this in practice. Here's a contrived, but not that unrealistic example about how you would do this. So your code might say, like, window.cat.computedStyle, measure something. And then based on that, it would set the height of something. And I would say, hey, how high are you? And then you say, oh, this other thing has to be size as well. And then what's your height? So you might not write code like this, but if you have a team of more than one person and there's more than one thing on the page going on, you're quickly getting into a situation where in each animation frame, you might do these various operations that are acting on various parts of the page. And it comes with a big problem, which is that browsers, when you read from the DOM or you say, what's your height, or what's your width, or any of these things that require laying out the page, they trigger recalculation of style, which means that they figure out how does their CSS affect the page layout, all those DOM elements. And so those reads trigger the style recalculation. And if you want to make an application that runs at 60 frames per second, you might be able to afford two of those, even though you really shouldn't. But at three, your mobile device is going to pass out and say, like, I'm going to jank this hell out of this. Fortunately, there's a very easy way to make this much better, which is to slightly change the order in which operations are executed. So like here, if you first do all the writes and then you do all the reads from the DOM, there's exactly one salary recalculation triggered. And as you can see, it's pretty easy to imagine that this essentially scales to an unlimited number of operations. Now it's really, really hard to manually write an application that's larger than one file to adhere to such a strict rule. So that's why there are helpful libraries that make it relatively easy. So if you're ever looking at the AMP source code, it has a library called vSync where you can say, like, I want to measure something, I want to mutate something, and then that library says, OK, I'm going to execute all the measures, and then I'll execute all the mutations. And outside of AMP, there's a very popular library called Fastdom that does a very similar thing. And it really helps with the easy API to make the DOM operations executed in an ideal order. With that, I want to move on to the next topic, which is analytics. So obviously, analytics is really important. Like, you want to know how many people come to your app, what they're doing, where they're clicking, how much time they spend, how they scroll. And that's really great. But what happens is sometimes more of them come in. And I actually have this, like, went through this myself where you would talk to the salesperson from the analytics vendor, and they would, like, say, we have this awesome new metric, and I'm like, yay. And so, like, we're switching to them, and then you realize that whether it's a new vendor, like, that's one thing you always report it to your manager, slightly dipped. And you do a lot of research, and you realize users, there's not less users. It's just that, you know, that new vendor interprets that metric slightly different. And so you panic, and you put the old thing back in. And so in practice, that happens all the time. And so we're seeing sites that have, like, five, 10, 15 of these. And it turns out that, you know, basically too much of everything is really bad for performance. However, we kind of challenge ourselves thinking there's really very little you can do about this being a problem. So would there be a way how you can have both? So essentially, all you can do analytics and still have good performance. And the solution that seems relatively obvious in retrospect is to separate instrumentation from reporting. So in AMP, the instrumentation, so the thing that measures your scroll progress, that measures clicks, exists only once, and it's built into AMP. And then it can report stuff to however many times you, as a developer, choose. So basically, what is the deal is that AMP knows how to talk to major analytics vendors and then just basically pinks them, says, like, user scrolled. And they interpret that information. And if you have, for example, in-house analytics or AMP doesn't directly support your favorite vendor, you can add configuration yourself. In fact, this is how it looks in the open source project. So just randomly chose come score. And this describes how to create a request when you track a page view with come score. So essentially, there's just a rule saying use this host and then this base URL and then put this stuff on the back. And so basically, you just have this configuration that says, given an event like a page view, how to construct a URL so that then come score tracks that as a page view. And this file is pretty long and basically for every major vendor and all the events they support has this small rule set. And that is how you can talk to them all but only pay the cost of figuring out when you need to talk to them exactly once. With that from analytics, I want to go to the final topic. And it's slightly different because it doesn't necessarily apply to the general web. And that is instant loading. So as I already talked about very quickly at the beginning, instant loading is achieved through pre-rendering. And pre-rendering means that you render something before the user said, I want to go there. So on a Google search result, that would mean we think they probably click on the first result. It's not the worst guess. So let's render that already. And that obviously comes with some problems, right? Because the user might not go there, but now you already use that bandwidth. And that CPU and a mobile CPU means battery. And that RAM to render the page. And that can be really problematic. And it was, in fact, so problematic that the native version of rendering, which is link rel pre-render, is essentially unusable on mobile. Now, to solve this problem, we went through a series of insights that led us from it being essentially impossible to working really well. And the first insight, which is, by the way, the most important insight when you think about performance optimizations in general, is that humans are actually kind of slow. And I mean that in the best possible way. So our reaction time is in the order of two seconds. So from that, you can say, in order to appear instant, you only have to appear instant. You don't have to be actually all the way done. And here's what that means in practice. So this is a typical website, right? No, it's actually not a typical website, because this is a typical website. It's really long. But for something to appear as having loaded instantly, the only thing that's really important is that the thing that I actually see when I go to the page is already done. Everything else, because reaction time is low, I can start downloading all the other images, for example. That instant where I show the page, when the user actually clicks it. So what AMP does when it's in free render mode, it will go and say any resource that isn't visible by the user, the instant the page is actually shown to them will not be downloaded at all during free render mode. And so that saves all the bandwidth that wouldn't have been necessary in the case where the user never goes to that page. It's pretty typical for a page that maybe have like one image or two images in the first report. But overall, the pages have many, many more images. And so not downloading them obviously saves a lot of bandwidths. That leaves the other problem, though, which is CPU and RAM usage on mobile, which is a big, big, big problem. And so AMP is relatively well optimized. And so we're pretty confident that CPU usage of AMP itself is OK. But AMP allows loading all these embeds. And so it might be YouTube videos, Instagrams, et cetera. And so first of all, AMP doesn't control them. And to be honest, some of them actually do use a lot of CPU. And for this reason, AMP does this. Was that all the way clear? Can do it again. So when AMP pre-renders the document, it will not actually load any of the extension implementation. So in the YouTube case, you can actually do really well because you can guess their poster URLs. And so AMP will put a poster on the page. And so it really looks complete. But the expensive part, which is the YouTube iFrame that loads like 500 kilobytes of JavaScript isn't actually loaded. And so when the user then expresses intent that they want to go to the page, AMP will immediately go and say, look, OK, we'll load the YouTube iFrame because now they might want to actually watch the video. But again, the page looks pretty complete. And so that user gets that gratification that everything's done, even though, in fact, not everything's done. And so with these two techniques, only loading stuff that's actually visible and only loading stuff where we know that the CPU usage and RAM usage is relatively minimal, you get the capability to pre-render pages on mobile where it's really basically infeasible with a general web page. And so again, like you have seen initially with the development equals, so on again, you can put a fragment parameter on any AMP document. I can try this in their browser and say, pre-render equals one. And that puts any AMP document in pre-render mode. And you'll see it's not really useful for yourself because there won't be any images loaded that aren't in the initial viewport, so you can scroll down and nothing loads. Same with all the embeds, they're going to be missing. But the page, as far as the first viewport goes, looks very complete. And then there's an equivalent post message API where you can tell the page, you're now actually being shown to a person, go load everything else. And that together gets that, that's how basically Google Search works. So in Google, it would load an iframe with the AMP page until it's your pre-render. And then when the user clicks, it sends a quick post message to the iframe saying, now you're actually being shown, go crazy loading everything you need. And with that, that was kind of all I wanted to talk about in terms of optimization. I wrote this blog post a while ago. It's under j.mp slash amp dash speed. And I do have the URL again at the end, which goes through the entire list of optimizations that all AMP pages have. And I'd like to say they cannot not have it because AMP really guarantees that those optimizations are applied. But I think it can also be used as a really nice resource, just as all the things that might apply to your non-AMP web page. Still, I'm personally very impatient, and I'm not satisfied at all with the speed of AMP. So what is your favorite AMP site is still too slow? It might use an extension that's not very optimized, or you might find that you find some edge case in AMP where AMP is slow. And I think that's actually the most exciting thing about AMP, which is that it can actually help. As an open source project, you can send a pull request, and we're shipping every week. So I think it's actually pretty amazing that you have this level of impact because every AMP page runs the latest version. So if you send a page to AMP, and you saw there was like 460,000 domains using it, a week later, they will all run your pull request. And so you can really make a big difference. And what I'd like to say is that this has been working so far, and we really want to thank all of you for sending these contributions. So AMP went into GitHub last October, and we've so far gotten to 1,950 pull requests. But what's even nicer is that it comes from 160 different contributors. And so I have a team, but it's not 160, not even close. So it's been a really, really cool collaborative effort. And again, thank you all, because we wouldn't have been able to do it without you. Few more things in terms of bookkeeping, because I really want to point to this. It's not actually a book, but I thought it was funny. So there's a website called ampbyexample.com. And so I'm personally, I know JavaScript is not the best rep developer. And this basically just has examples for all the things you might do in AMP. And it has both the output and the source code. And it just copy, paste yourself to happiness. It's really useful if you want to get started with AMP. Another shoutout is that Google actually yesterday launched an API called the ampurl API. And so this is applicable to you, not if you want to make AMP pages, but if you have either a web app or a native app that has links. And you might want to say, it'd be good for our users if we pointed them to the AMP version of those URLs. And so you can call this URL and say, hey, is there an AMP version for this? And they will say yes or no, basically. Coming from this, it was first shown yesterday. And it's a topic I'm super excited about. So my talk is almost over. I would ask all of you to go to the amphitheater after this, 3 PM, where Alex Russell will talk about how AMP relates to progressive web apps. And it turns out that those work really, really well together. There was this nice demo yesterday of a Washington Post, which totally impressed me. And also it's an enneagram if you turn around the W. Anyway, that's really all I have. Here's a link to our docs, our GitHub, and again, the blog post. Thank you very much.