 Good afternoon, guys. I'm Sriram. I work with Mozilla, and they are Firefox for Android application. I started there about two years back and been part of major rewrites and performance improvements. Since it would be hard for you guys to associate yourself with Firefox and understand why we did various performance improvements in various places, I've come up with a demo application called Shutter, which is just another photography application. It uses a card UI. Here is a quick demo of the application. It uses infinite scroll. As you can see, whenever a photo is loaded from the internet, like the server, a gray background is shown with progress bar, and then the actual image is being shown. The same thing goes for the profile views as well. Let's take a closer look at the card. Here is how the card looks. It uses a profile image of which is circular, which you can see in Google+. And the actually has a name handle and all the stuff just like in Facebook. The bottom bar is just like Facebook, and the contact icon shown there are like Google+. Hope this makes you feel better about the UI, associate yourself with the UI. So given an app like this, what are the tools we have at our disposal to use and optimize the performance? To start with, there is something called a show GPU overdrive. This is part of the Android developer options. The idea here is pretty simple. Whenever a frame on the screen is updated or whenever a screen is refreshed, every time a pixel is changed on the screen for a single refresh, it is called an overdrive. In this case, let's say there is a text view with the background. The first time the background is drawn, there is literally no overdrive. But when the actual text is drawn, whenever each and every pixel on it is being changed on the background, it's called an overdrive. It is actually represented as a color map, one X being blue, twice two, amount of overdrive is represented as green, thrice is red, and anything more is deep red. As you can see, this application has a lot and a lot of overdrive. Starting with KitKat, they have introduced a small little counter at the bottom, which is an aggregate number, which again conveys the same meaning. Around, this application has about 3.86 times overdrive. Around two Xs fairly uncured for scrolling performance. The next tool we have is called profile GPU rendering. This is again a part of developer options. The idea here is it shows a graph for every time the screen is being updated, and there is a small little green line. The contrast isn't that good, but there is a green line at the bottom which shows a 16 millisecond mark. This is the time each frame should take for the screen to refresh at 60 hertz. If, say, here is a demo of it, if, say, there are spikes or the 16 millisecond mark, what exactly that means is it is taking time from the next frame, which means the next frame would be choppy. Like you can see here, it's a bit choppy, but this phone is running KitKat, so there are a lot and a lot of performance improvements. Unfortunately, on jelly bean, the spikes are super, super high, which means the app is performing super low. These tools will help you understand the state of the app. There is one more tool, which is a command line utility. It's called SysTrace. You can check how much each and every function or even methods are taking. Starting with Android 4.3, they have introduced a class called Android OS Trace where you can have your custom events and monitor it by zooming into this. This is basically a HTML generated by the command line utility. Currently, it takes about 30 milliseconds, let's say. So we have an app, we have a lot of tools, and we know the app is performing worse. What sort of techniques can we use before that? So these tools, the problem is we don't have a context of what the entire view hierarchy is and what views are being rendered at any given time. So I wrote a tool called Drive Inspector. It connects to Eclipse. It can be decorated with DDMS. This is how it looks. It shows a 3D view. So you can clearly see if any background layers are actually rendering any content and you can write it this 3D model. Clicking on any of these views will show you how var exactly the view is in the hierarchy. The tree view also has checkboxes, so you can selectively show height content. And there is a box model to which shows the actual bounds, dribble padding and all the stuff. You can see the wardrobe of the application directly, tweak these controls to see how it reflects on this wardrobe. If time permits, I'll show a quick demo at the end of this talk. So we have all these tools and what sort of techniques can we use? This is the code you need to add this Drive Inspector to any application. Moving on to the techniques, the first thing one should do to optimize an app is remove overdraw. At any cost, remove all possible overdraw. Let's see how much overdraw Shutter has. As I said, it has a lot and a lot of red parts. This is the 3D view taken with Drive Inspector. If you can see, the far left one has a wide background and then there are a few more layers drawing more and more content, which is obviously causing the overdraw. Here is the card. Here is the wide background drawn by Android. This is the window background. And then there is a list view background and then there is a wide UI for the card and then few more layers on top of it. As I started saying about the list of backgrounds, the first one is a window background. This comes from Android. Usually, all apps inherit themselves from either hollow or hollow-like. And these themes by default add a background so that when you tap on the launcher icon and then open that, it doesn't feel odd. It has some background to start up with. This is also good to have splash screens, but usually people don't like splash screens or you can use a dominant color of your application. But, or the cause of the application, this background is pretty irrelevant because we will be adding more and more content on top of it and this is not even seen by the users. We can mitigate this problem by removing the background drawable by just calling git window.set background drawable. This will remove that particular layer once that particular activity gains focus. So in our stack views, we can just remove that layer. When you look at the images, like the profile image and the actual image, they're actually having two different backgrounds behind them. The reason is why up until an image is being fetched from the server, it's good to show some sort of default image like a plain background or something with a progress indicator. But if you are setting a background for an image view and then setting a bitmap for the image view Android treats it as two different things and draws them both, which means unnecessarily we are drawing a background which is again an overdraw. This is kind of pretty relevant. I've seen in pretty much many applications in the market today. So a good thing to do is once an image view has a proper bitmap set, it's better to remove the backgrounds. So these are the layers we would currently have if we do all the stuff. Let's take the images out of context. All we have is a list view background, the white from the card and a small pale white at the bottom, bottom, bottom bar. How about we merging all these stuff into a single layer and what would that look like? This would pretty much be just the same as the card UI. When we do something like this and set it as the background for the card instead of having a background for the list view and for the card, we are actually reducing the order of the card and the list view. This is, actually there is a transparent region in the middle but it's not clearly seen. The check word is not clearly seen here. That would help even the image view to avoid overdraw. This is sort of a technique used by Facebook app on their Android application. So with this, we could reduce overdraw a lot. So the first step is done. The next one is reducing the views. Let's take a look at the number of views used for a single card. It's about 50, I would say. The problem here is, whenever a frame is being drawn, it goes through the entire hierarchy and checks if it is visible and then execute the draw commands. As long as the view hierarchy is really simple, really small, it takes less time to draw each and every frame. It is said that if you have around 55 views to be drawn in a single frame, then app would perform better. How can we solve this issue of so many views? The first technique is Compot Drawables. People started knowing this pretty late like about one year back and the idea here is if there is a small little image like a status icon and an accompanying label, instead of using a linear layout with two different views in it, you can combine them and have it as a single text view. You can also have an icon on the right and the good news is these drawables support animations and states. So if you set a state on the text view, it will be passed on to the drawable and the drawable can react to that. So we can use the same technique for these buttons and for these status icons. So it has a small little image and then a text following it. And you can also use it here. This is the actual code you would be writing like a linear layout with image view and a text view. All we need to do is take the source of the image view and set it as drawable left on the text view. This would create a compound drawable and the drawable padding is basically the space between the image and the text as such. In case you are loading images on the fly from your server and setting it up for a text view, you can do that using set compound drawables in Java side. The last one is pretty new. It has for RTL layout. So instead of left and right, you can specify start and end and it will automatically switch the images. The next one is spanable string. We all love span elements in HTML. In a big blob of text, we can change a particular color or foreground or anything in HTML. And right supports that too. The screen chart you see in the right, it has one single text view with the different elements like foreground color, background color, everything applied to it. Adding this is again easy. You use a spanable string builder with the intended text and then you can create any span like foreground or background span or even a text appearance span. You tell the builder, this is the span I need to use. This is the start index. This is the end index and set that for your text view. This can be used say for anything where there is a username and a handle. Like the handle could be a text appearance span. This is pretty useful here where there is an image span, some text and then an image span and then some more text. All this enclosed in one single view. We've flattened the hierarchy a lot. And here as well. All right, let's dive a bit more into the canvas and see what we can manipulate in the canvas and improve the performance. So here is the profile image. Think of the red square as the actual image that's been downloaded from the server. Now there are two options to show it. Either you can show, you can download a circular image and then show it, or you can download a square image and then have a mask over it to make it feel like a rounded image. But if you are downloading a rounded image from the server, it won't fit here because those are again profile icons which are of similar size, but it has some rounded edges or something like that. To avoid this, we can use something called ported-off modes. Ported-off is basically alpha compositing. What it really means is if there are multiple images that are going to be placed in a single view or anything, the technique you apply to merge all these images into a single final image is called compositing, and this can also take care of alpha 2. So given a destination and a source, it has different modes defining how to merge them both. Here is an example of it. The white is the canvas, say for a view, and the blue is the one that has already been drawn. It is the destination. The red square is about to be drawn. For a mode like source-over, which is the default mode, it would just draw on top of it. But let's say we want to have the red behind whatever is drawn on the canvas. We can use something called destination-over, in which case the blue will be on top, which was the destination. The more important modes here are destination-in. This is, this can be used as a mask. So say you have a circular mask and you want to crop an image with that circular mask. We can use the circle as the source, and you can apply this. This is the opposite of it, which is like clipping a part of a region from any shape. So in our case, we can draw the bitmap first, which is our destination. It's drawn on the canvas, and the source is a red circle. When you use this mask on the destination, we achieve the circular image, which is exactly the same thing we wanted to achieve for our profile images. We can even use any other shape, any odd shapes, and using destination-in, it would give a masked output. Here's the code for it. I'll walk you through it, it's pretty simple. So you ask the parent to draw on the canvas. This is the destination, this is our bitmap. Then you create a mask. The one thing to note with Portrait of Modes is starting with Ice Cream Sandwich, the entry is double buffering. So you don't have to create an off-screen bitmap, but anything before that, you would have to create an off-screen bitmap. And in that bitmap, you're actually drawing the intended mask. In this case, I'm drawing just a random path on it. Now take that path and draw it on the canvas using a paint. The paint has the Portrait of Modes set as destination-in. This would give us the intended result. So this can be used for these profile images and the images here. One thing to note with these small images here is that they even have an alpha, which we can solve using some other approach. The next complex part that you can use with canvases are called shaders. If you have done some OpenGL development, you'd know about vertex and fragment shaders. This is almost same as that, but it's abstracted for Android level. The simplest shader I can think of is a paint with a solid color. So any paint object you can use to draw on canvas is a shader. The pretty primitive one out, one shader is a bitmap shader. It can draw a bitmap on the screen. And using a path, if you are going to shed this shader on the paint and you are going to draw a path, you would get the intended result. So creating a shader is simple. You use the bitmap, the required bitmap, and the tile mode is important. So if you don't want the images to repeat, you can use a clamp mode. Say if you have a really big canvas and you want to use a really small, tiny image and repeat it for the entire canvas, you can use a tile mode like repeat. You're setting that particular shader as the shader for your paint. And your draw operation is pretty simple. Can use a draw path of required path with that particular paint and you would get the intended result. One thing to note here is please avoid creating shaders inside draw calls or on draw calls. The reason is for every single frame, you are going to create more and more objects and at some point in the future, GC is going to be called. These are pretty constant shaders. They can be created outside of draw calls. Is that all we can do with shaders? Sounds like no. So say you have a shader A and a shader B, you can use the same product of modes and then say how to apply shader B on shader A and create a composed shader. So if you have a bitmap like this using a bitmap shader and you have a linear gradient going from black to transparent, you can use the same destination in as a mask and get a nice gradient feel for the image. So if your application uses a reflected image view or something like that, you can use this. You can use this for getting VNR effects or there are even more shaders that can give you different saturation colors and all those stuff. Creating this again is easy. The same bitmap shader like the previous example, you create a linear gradient which in this case, it goes from the top to the height of the bitmap and the color is from black to transparent. Now you tell the paint to create a composed shader where bitmap shader is the destination, gradient is the source and you're applying the same product of mode destination in and the dark color is pretty much the same because the paint knows how to draw that particular shader. So we can use these shaders here. Like I was mentioning these images have a bit of alpha on them. So you can use linear gradient from 20% black to 20% black and you could achieve this easily. A few performance things to note with shaders are, one, they don't need off-screen bitmaps so they are much better than ported off modes and two, even if it is a composed shader there are, it is all drawn in one single call on the canvas. So the paint will call the shader and the shader will give the result to be drawn on the screen. So even if you have a bitmap shader and a gradient and create a composed shader the result is just one single draw operation on the canvas. All right, can we do much more than this? So let's say you have a view like this with three simple images or say you have a rating bar where you have to show three different stars and so on. If you had to use a linear layout and then add these images, of course it would work but we are adding more and more views for every single element in your list row or anything like that. Instead, we can kill all these individual images and we can create custom views that knows how to draw all these stuff. This, all we need to do is override the measure and the draw calls. In this case, I'm just calculating the number of children to be done and then the size of each child and then finding the width of the entire view. Please note that this is one single view. So the width has to be set back on that particular view using set measure dimension. And the draw call again is pretty simple. So you translate to the intended position, draw the particular bitmap and then translate again, draw the next bitmap and so on and on. This way we can reduce a lot of views too. All right, we've walked through different techniques. We've done a lot of performance improvements. Let's see how much performance gain we've got. This was, this is the final view hierarchy. So on left, you could see a bit, while G1, this is a pretty small application so you won't see a really big one but still you could see a lot of layers which were obscured and now on the right you see is the final one. As I said, if you can see behind those images there is a transparent region that helps avoid more overdrive. This was the big list of like 50 views per card we started with on the right. It's about 10 views, which is really good. So if your screen is going to show like three different cards, you would end up with about 50 views at max for your entire hierarchy. We started with about 3.8x. This on the right you see there is no order at all. Just blue parts only for the regions where we are drawing. And here is a quick demo of the scrolling performance. You could see a few spikes or the 16 millisecond mark. And on the right is the one with all these performance improvements. This is on KitKat. So you won't see much of a performance improvement but on Jellybean with these techniques I could see a lot and a lot of performance improvement. All right, this is the final output. This is where we started with. It's starting a bit here and there. This is the final output without any problem. I've also used a few more techniques on the right. I don't have time to cover all those. You could use LRE caching, which is really good. That would help us avoid OEM errors which we always have to fight. And this is the Cistray's output. It's about eight milliseconds. Do you guys have any questions? Hi Suryam. I have an app which displays a lot of spanable string. You can say huge text, maybe around 2000 characters. And it has color, bold, italics. But when it comes to setting the text, when you call set text, it lags a bit. And what happens is I need to set the text quite often. Okay. So is there a way to optimize that? And do you know if you compare that with the HTML class? Is there an improvement if you just need to set it bold and italics? I haven't tried using HTML dot from HTML. It is good as well. But as long as you don't set it on, if you have really large text, probably you could break it up into multiple text views and try it. For our cases, we have used in pretty small places, like pretty much small blobs of text, not big stuff. And we really saw a lot of performance improvements. Unfortunately, in my case, it's one scrollable text view. So is there a way it can still be optimized? Probably in that case, you could go directly deep into the text paint level and then do your operations there, like store the information that you want to paint with yourself. So in one of our examples, we had to show a gradiented effect on our text when instead of showing ellipses. In that case, we use a linear gradient directly on the text paint to do it. So you could do any such operations directly on the text paint. And probably that would be a win for you. Sure, thanks. Hey, Sridha. Yeah. My question is how expensive is fine view by ID and how does it work internally and is there something we can do to optimize it? So find view by ID, if it has to do it from the root, it's going to go through the entire root hierarchy and then find it. It is a good thing to cache all those views and store it. So the view-hunter pattern came into existence. But ideally, it's not good to do it when there is a scrolling thing, like in list views and stuff. Hey, Sridham, one question regarding the first point you had about avoiding unnecessary backgrounds. Are you saying that we need to explicitly set the background as null for all the views when we don't need them or is avoiding the key altogether enough? So first thing, if you are using a window background, let's say if it's like a WhatsApp, it has a nice little background for each conversation view. You can set it as a window background and it would just work fine because there are just blurbs on top of it, like the conversation and stuff. But if you are using a background that is not going to be seen by the user, it's better to avoid it. And the best place to do that is in on-window focus changed event. No, like say for example, image views. Now that has two keys, right, background and source. If I don't specify background at all, it won't take a default background, right? Right. But in my example, I was using a background so that something was shown until the actual image has fetched from the server. Thanks. Hello. My name is Arun. In using large bitmaps, we will usually get memory allocation at all, right? So how can we solve that issue? So let's say these images are fetched from the internet and you double tap on this so it can show a really bitmap and stuff. The good thing to do is save it on the disk and create a scale to drawable, depending on the screen size and put it in a cache. As long as you are putting it in a cache like a memory cache, a lary cache and using it from there, we haven't seen any out of memory errors as such. But if you are directly accessing the bitmap, using a really big bitmap and then directly using it for these image views, one, it is going to do scaling when it is about to be drawn and two, it is going to cause these wire mirrors. So good thing. Actually, we can scale it down because it's kind of map, we have to zoom it. So when we scale down, it's clarity will go down. So if it is one single image, you can just use that and show parts of it or probably, you could probably create, play with these shaders and create a multiple image map and things like that. That would also work. You can split the image into multiple parts and based on scrolling, you can load different contents. Okay, you need to split the image into different parts. Yeah, you can split it into different parts and then you can create different shaders and then play it. Okay. Yeah, I am Amit. Actually, I want to ask one thing on the UI related points. Like if we want to change our controls or layouts dynamically on one page or one layout. So is there a best way to do it or just using the stub layouts and then loading the new ones? So any efficient way on that? Like if we have four, five layouts and we want to keep changing on that dynamically. You could use fragments in which case you can, it has a really good performance benefit and it does memory management for you. So only the views that are going to be shown are kept in the memory. Other are not kept in the memory. That is really good. If you are going to switch between four, five layouts. Other than fragments, like any other native and write things, like fragment came later, right? That is support even for older versions too and we started using it. We've seen really good improvement with that. Yeah, like if you just want to avoid that fragment part just going with the previous version. So is there a way again? One thing I could think of is you could probably detaching from the view hierarchy and then attach it whenever you want, but that would have an inflation cost. Depends on when you want to inflate it and if it's not seen by the user, it's a really good thing to do. Hi, I just want to know, do you use any kind of library for loading images? We don't have that much images to load as such for Firefox, but one of my colleagues wrote a library called Smoothie. You can check it out, lucasr.org slash smoothie. It helps us in loading images from the net and it also has a lot of performance benefits for list view scrolls and stuff. Okay, thanks. Any tips on animations and making them smoother? The newly released library from Android is really good. We started using that and it, so the nine-hole drive is also a good library and we actually wrote our own wrapper, like not even wrapper, we wrote our own animation core logic and stuff because we didn't want to use any external library for licensing concerns because Mozilla is open source. So, as long as you use with Jelly Bean and all this stuff, you can use a hardware layer. So whenever you are animating, you can back it up with a hardware layer and then do the animation and once the animation is done, you can set it to null. That way, the animations are smooth. In older cases, we can use direct matrix translations and stuff. That's what we are using in our custom code. We have five more minutes. Any questions? You can also connect with the speaker in the speaker connect space available. Thank you. Thanks guys.