Android Go is the next billion devices and a limit of 50 MB. Lecture of Yandex
New directions for the development of the already familiar platform are always interesting. On the one hand, you expand the client base, on the other - do not invest in creating software from scratch, and use existing work. But if the direction is really new, with its own specifics, then it will not be possible to manage very little blood. At a regular meeting of the Mosdroid community in our office, the developer Arthur Vasilov talked about adapting the Yandex application to the Android Go system.
On average, if you do not write a calculator, an alarm clock and so on, then either you are very classy, a great fellow and all did well, or your application takes 150-170 megabytes.
this report . Who watched it?
Excellent. All the other 180 people know what to do in the near future. In my opinion, this is one of the best reports on Google I /O. The dude told unrealistically cool things. He told everything on the shelves, well, and with many deep details. Those who looked at it and remember it well, for certain will notice that I from there copied some things, because otherwise it is impossible, he told everything, so I will repeat.
What do we measure? There was such a thing called PSS (Proportional Set Size). That is, the RAM in Android is represented by some blocks of 40 kilobytes, and these blocks can both be completely owned by the application, and can be rooted between processes and applications.
And the question: how to understand what application to include this shared memory? There are several approaches, they are quite logical. PSS says that if memory is bugging between N processes, then we will assume that your application has 1 /N of this memory. And absolutely similar is Residential Set Size and Unique Set Size, which says that "Nothing of shared memory belongs to me" and "Everything belongs to". In principle, PSS here is the most logical.
How exactly can you measure the memory consumed? Here everything is simple. Either this is a profiler in Android Studio, or it's dumpsys. There are, of course, other tools. They can give you more detailed results, something more complicated, but the problem is that to understand their results, to use them all, this is very, very difficult. Often you need either root or custom build of Android. And they do not really need you, the first two instruments are sufficient.
On the profiler in Android Studio, I will not speak, I think, many used it. Who has not used it, be sure to poke it. In particular, I cited the link below - just a good article from the video documentation, how to use it, with demos. And, in principle, everything is clear. It shows where your memory goes, shows it in real time. The only thing to remember is that he does impose certain errors that arise from the fact that we constantly measure this memory. But they are within the limits of the permissible.
Dumpsys is a simple console piece that does not require anything from you, just a connected phone and adb. And you can execute this command: call dumpsys meminfo, pass the packet to it, and it will return something like this. And if we are interested in how much our application consumes, we can look specifically at TOTAL, which says that "your application eats about 168 megabytes". A lot, but what to do?
Also it shows you the breakdown, what exactly in this consumed memory is how much space it takes. There are different parts here, they are complex, we'll talk about them further, but for now we can notice the main thing - it's Java Heap, our java objects, and everything that's next is more complicated.
What else is important? Memory is a very sensitive thing to any tests and all external conditions. That is, you must perform all tests as much as possible under the same conditions. It is clear that this should ideally be one device, because the memory depends on the version of Android. It is enough to recall the differences between the fours and the fives. Depends on the size or resolution of the screen, because the larger the screen size, the more content it gets, the more memory it takes to render it all. Resolution The larger, the more pixels your bitmap occupies, and the more memory is required for their storage.
The script for working with the application also affects the tests. You can read the text or you can scroll the gallery with a bunch of pictures. And it is clear where there will be more memory.
Another important thing is the workload of the device. That is, you can have everything the same, but in this case, you have your application is the only one that works, and in another case you have a lot of applications that do something else in the background, do something, download, delete, work on foreground , and at the same time your application simply squeezes the memory, because you have to give it to other applications. So, ideally, it's better to kill all the other applications that work, not yours first. All that you can reach, kill. Simply in this case, and PSS will exactly thank you, because you will not need to fumigate the memory between the processes.
You can, for example, take and view the current information for free memory, by using the memory. He will bring you about such a tablet that says that "I have so much free memory, there is so much cached memory, so much memory". And if you have 200-250 megabytes of free memory for yourself, then it's good, most likely, then nothing will affect your tests.
Probably, someone now had a question "Why do I need all this?". This is such a break, in which I will additionally say the motivation for all this.
First, even if you are not going to do anything for Android Go now and think that it is dead, it may well develop, come to you, and you at some point will have to deal with all this.
The second thing that I consider very important is that you can simply do regression tests from memory. That is, you can simply write a script that will run the application, do dumpsys, perform such measurements, and see how you change these metrics between releases. This script can be written in a couple of hours, configure the infrastructure - longer, but, it seems to me, this is a good thing.
If we talk about the specifics of Android Go - our third point in the fight against memory - then there are some nice news. First, no one really requires you to follow these restrictions. That is, you can use the application, as you have it, put it on your device with Android Go, and everything is fine. The problem is that the user is very likely to delete you, because you occupy a lot of space. Also your application can work slowly and there is a heap of memory, yes. But so far no one forbids this, because otherwise there would be no applications, except Google's on the Android Go. But if this thing continues to evolve, many will adapt to such conditions, then, in the end, your application can simply be lowered in the rendering of Android Go, or tell how the user will install the application on his Android Go smartphone, he can show Alert : "Dude, the application does not work well with Android Go. Maybe you will not bet it? ".
There is one more thing - you can use your hands on Google Play to exclude Android Go devices, that is, say that the application can not be placed on Android Go devices. It appeared not so long ago.
And Google is also smart enough, and 50 megabytes that sounded in the title of the report is not a fixed figure, it depends on the device's resolution, screen size, and, in addition, on the type of application. For example, the games are allocated more, in my opinion, 115 megabytes. In principle, this is quite understandable.
What about the test itself? There is another point, which in particular very much concerns us - working with presets. When vendors make a new phone, they often put there a set of preinstalled applications. In particular, we are very much engaged in this, and the problem is that there they run things like the Compatibility Test Suite. These are Google tests, they drive them away. And there, if your application does not correspond to these 50 megabytes, then everything is bad, and your application can not be pre-installed on such a device.
Unfortunately, the tests Google does is not from open source, I can not tell them, they are under NDA, but good developers from Google wrote such an article about Android Go, and there, in principle, there are recommendations that are quite good
That is all trite. Run the application. We are waiting for 5 seconds, until everything is loaded. We make dumpsys, write the value of TOTAL, execute a bunch of times, get the result. It's very simple and trivial.
The only thing they did not take into account such a small feature in their article, or, perhaps, did not talk about it - is such a thing as working in another process, and often it is done to fight, including with memory consumption.
Who believes this is good for Android Go? And who believes that this is bad? Boldly.
The problem is that, yes, this is bad, because in the end your consumed application memory is considered for all processesitself. If we make such an empty process without anything and take dumpsys of this process, we will see that it occupies 7 megabytes. 5-8 megabytes is such an overhead projector from the creation of the process. Therefore, when we fight for every megabyte to squeeze it all in 5? then such a thing is given to us very badly. In particular, say, Yandex has the most popular Yandex.Metrica library, it also works in a different process, and this, too, can give us pain.
Therefore, if you come to, say, some external libraries, you can just say: "Dude, work, please, in the main process. I agree that it can be slower, but it will not waste extra memory. " So this is also a delicate moment.
If we talk on the consumption of memory, then let's move on to this plate, which is there. We take an empty project, and run this dumpsys, set it on, and see that 23 megabytes out of 50 is already taken. Empty "Hello, world!" Without anything, just activate with the text. It's getting pretty sad. Even more sad is the realization that we can directly influence the parameter such as Java Heap, that is, it directly our java objects, which can be tracked explicitly, which we can delete, reduce and somehow interact.
And with this whole thing it's difficult to interact normally, because this is any frameworks code and directly from Java, you simply do not have any normal tools to understand how all this is used. But the good news is that we can influence this whole thing indirectly, so let's talk about what's there.
What is Java Heap - it is understandable. What is Native Heap - also logical enough to assume. These are the same allocations, only positive ones. They come from the framework and from your native libraries, .so files, and so on.
The code is directly related to the storage of the code. This is the size of your .dex, it's your .so, it's resources, mmap-files and all that. That is, the less code, the better. The simplest truth that works at all about everything.
Stack is a Java /C ++ stream stack. That is, each thread has its own call stack, so each thread creates such a specific area of memory to store the entire case.
Graphics is the rendering of a UI. There are partially stored and bitmaps, which are drawn, and what is connected with this.
Private other, System is something that we can not really influence at all, and, in fact, everything else that does not really lend itself to categorization.
If we talk about native libraries, then, for example, you can take an empty application you can take the usual application that we have, and take dumpsys from it, see that it occupies 146 megabytes. And if you go and cut something in particular, I took and sawed out the two largest native libraries, which we have in the amount of 15 megabytes, and take dumpsys after that, you can easily see that we have lost consumption from Native Heap and from the code. That is, with such a simple gesture we saved about 35 megabytes. Quite good.
Streams. Let's do the simplest test. There is an empty application, and there is the same empty application where we take and make a loop that will make new Thread (), in it sleep for five seconds, and start this thread. You can see that in this case we have a lot of stacks. That is, we can influence the whole thing, but indirectly, by reducing the number of threads in the Java code. That is, through Java objects, including affect all these locations, which are in other elements.
If you continue to talk about threads, you can easily see what you have for the threads that they do in the application. There are different tools. You can use the same systrace, you can simply find the id of your process by the console, and grasp the ps by what streams are in the system at all.
If you do well and use all sorts of ThreadFactory to name your threads, then you can understand what you should have, what should not be, and thus reduce the whole thing, because 100 threads in the application have especially meaningless.
What else can I do? There is a completely well-known set of bayan tips: watch for leaks, use pools, do not create objects when you do not need it, and all this nonsense, all this applies. Excellent.
There is a good relationship between how much your application consumes memory, and how large it is. That is, the more your application, the more memory it will consume, so, in simple terms, reduce the weight of APK, reduce the weight of .dex, reduce .so, remove everything that can be removed.
Memory reduction is incredibly poorly matched with optimization. Let's say we want to make the most simple case, when a user scrolls a picture stream, images are downloaded from the network. What do we do in such a case that the user sees the pictures faster? We are in advance - until he has not already completed these pictures - we start to load the necessary pictures so that he does not see the gray squares. In this case, if we are talking about memory, then we will simply take up memory with these pictures. Therefore, memory and optimization are extremely poorly matched. In the sense of optimizing this type.
If you look at dumpsys, it's good, it shows you a lot of interesting things, except for directly consuming memory. For example, the number of your objects, such as the amount of View, the number of WebViews, the number of Assets, information on databases.
In principle, databases do not take much, but perhaps if you are critical of each kilobyte, you will have to use SharedPreference instead of SQLite in some cases, and perhaps this will help you.
Also, for example, it's very nice to look at the dedicated Assets. In particular, the most popular thing you can see is the fonts. And these fonts occupy 1.5 megabytes. Again, when we are fighting for every megabyte, then tender design feelings are sent far in the first place. Yes, my colleagues will forgive me.
Unexpectedly, a disgusting thing is WebView. If you create an empty activity, start WebView, load the Yandex page, take dumpsys, it will be 100 megabytes, just right away. If you open, say, some pictures, scroll a couple of times, then 300 megabytes - easily. Even though the WebView is Chrome, and the process is considered yours. So that.
Google knows this. They made a small hack. That is, they have WebView, they have a Google application in which you can search for something. Search output is opened in WebView. Fine.
And there is a Google Go app that is designed for Android Go devices. And here they open the issue already natively, that is, they create some sort of layout for displaying this issue, they display all this with native components. And everything you need to open directly in the browser is not opened in your internal browser, but in Chrome Tabs, so that Chrome understands this case. Such are the tricks.
If we talk about the application directly under Android Go, then what's interesting? There are certain specifics about how to develop an application for Android Go, and let's talk about it a little.
There are several ways. First, you can all be cool, the application can work well, and you can give it to Android Go without any modifications. The same is true if you are writing an alarm clock, a calculator. But most of the time you have this complicated, so you need, say, do some build flags, disable some modules, features at the compilation stage, and do something else. And so you will have two APKs, and you can load one as normal, the second - use uses-feature "low-memory", and it will be like two APKs.
Or you can make two applications, that is, one application is normal, another application is specially sharpened for Android Go. So does Google. They, in particular, released Go-versions of many of their applications.
What's good, what's wrong with it? It's good that you initially make a new application, and if you initially write something in it and exceed memory consumption, then you will say: "Yeah, I did something wrong. I went to do it normally. " And you do not need to immediately reduce this memory four times. In addition, it's good and it's easy, but it's bad that you need to make a new application, besides, it should be somehow maintained, the same as with the main application, and somehow it should be combined. This requires a huge amount of resources, and in principle, you do not need to do this if you are not Google, because if Google does not make such applications, then no one will do it. And now you do not need to do such an application, because it requires a lot of resources, and it's unclear whether Android Go will shoot well, and there will really be a lot of such devices, or it will be a pretty niche share.
In any case, a multi-module approach is very helpful here, because you can easily disable the modules, something else. It is very good.
Another rather important point from the report, which was on Google I /O: the guys correctly say that we should not be afraid for such weak devices to disable some of their features in runtime. Perhaps you have a very cool photo editor that can do anything, apply any filters, but it requires a bunch of memory, and on a weak device it will work badly. So do not be afraid to say that "Let's not run a photo editor on your device, because you have a weak device. Buy the normal. " So this chart is good. This is a graph of the dependence of the number of features on the consumed memory, and vice versa. And this can be followed, in principle.
What else is worth considering? It is clear that this is not just a question of memory. Memory is the most difficult, the most interesting, and the things that we've been working on 98% of the time. But it's clear that you need to think about speed, startup, battery consumption, etc. Besides, you can do some additional features for Android Go-applications. In particular, YouTube Go has the option to download the application for offline viewing. In the main YouTube application this was not, and maybe not even now. I do not know. The fact is that devices with Android Go will be used in countries where, perhaps, not a very good Internet - so let's download in advance. There are other good examples - Facebook Lite, Twitter Lite, as well as Yandex.Browser Lite, because not everyone needs any fully functional features. Someone, maybe, needs only correspondence or just posts. No need to download a huge Facebook, when you can put a little. And all this should be for users, you have to think and do so that they feel good. In general, this is a cool impersonation - to make such an application that it works under Android Go.
What else on ssylochkam? There are classy answer on Stack Overflow, which scored almost ?000 likes. You can help him score more. The answer explains that, in general, with memory, what is responsible for what is in memory. And, in principle, all this answer is for dumpsys.
Whether many know it or not, but Android can work with devices that have 512 megabytes of RAM, only starting with Android 4.4. There just appeared special API to interact with such devices, and this can help you.
Here it would be possible to finish, it would be beautiful. And now about how it really was in our country. If shortly - not so beautiful, not so beautiful.
They came to me in May, they said: "We must do it." I said, "All right." Went to understand. Honored - everything is good, except for memory. The memory is somewhere around 170 megabytes. Great start. We must somehow reduce it. What is easiest to do? Take and disable all disabled modules, see what happens, because you have to make it work somehow. If there will not be any features - well, okay. There are 105 megabytes left. It was painful.
Therefore, a lot of refactoring went on. Based on the build-flag, the conversion of everything has begun. Have made densitySplit, so that resource tables occupied less, resConfig, left there only Russian and English locales. The cache of pictures is twisted, preload is removed, all optimizations are removed - pain. ProGuard is even more tweaked. In particular, ProGuard has inlinening, which allows to reduce the number of methods, and in exchange, perhaps, to sacrifice performance, including readability in stacktraces.
Then there was already quite a lot of refactoring. The transfer is even more in modules, so that all this can be turned off, so that it's beautiful and that the Android Go application can be collected from our main application.
After a week, there was somewhere around 64 megabytes. I think: "Well, we must finish today." It's been 14 hours, time is 4 am, memory is 60 megabytes. And I do not know what to do next. I'm rage. Moreover, it has become irreversible refactoring. Therefore, the next morning, a strong-willed decision was made - it's all not the same, life is disgusting, I hate everything, and we're making a special new branch, starting from scratch. We take and delete all the code, which, most likely, should not be in Android Go, and fix compilation errors. 10 hours, APK with the rest of the basic functionality is ready, the tests pass, perfectly. The problem is that this thing is unsupported, we have it all.
Thus, the best solution is the second application. However, few people will spend resources on it, while the real profit is not clear. Perhaps your story will not be so sad, because I have a little effort, I would have climbed, but I was already unbearable. But this is the story. On this relatively positive note, perhaps, you can finish it. Thanks to all.
It may be interesting
This is my first time i visit here. I found such a substantial number of interesting stuff in your blog especially its examination. Really its inconceivable article. Keep it up.Gulf Coast Western Reviews
I can see that you are an expert at your field! I am launching a website soon, and your information will be very useful for me.. Thanks for all your help and wishing you all the success in your business.GSM Solutions
Wow, What a Excellent post. I really found this to much informatics. It is what i was searching for.I would like to suggest you that please keep sharing such type of info.Thanksthc vape juice