ARC++ is the runtime that allows you to use Android apps from Google Play seamlessly on ChromeOS. ARCVM, the latest implementation of ARC++, uses a virtual machine to run the whole Android stack as a separate operating system on top of ChromeOS. While this is great for compatibility with demanding apps like games, running two operating systems simultaneously on the same machine is challenging. Sharing the CPU and memory among ChromeOS tabs and Android apps can lead to performance issues and increased power drain.
To address this, we’ve made changes to ARC++ to minimize the resources it consumes, especially when it is not in use, while still allowing resources to be directed to Android apps when needed. These changes include three recently launched features: improved memory ballooning, Doze Mode, and ARC++ on Demand.
Improved memory ballooning
ChromeOS operates in an extremely memory constrained environment making it challenging to determine which tasks should be allocated memory at any given time. ARC++ makes use of Linux’s virtio-balloon device support to dynamically shift memory allowances for ChromeOS and ARC++. To make efficient use of the memory balloon, though, we need a policy to determine when, and how much, memory should be shifted.
To address this, we developed a new memory ballooning strategy called the VM Memory Management Service (VMMMS). This service determines how to adjust the memory balloon by looking at several signals, including if there is low memory pressure or high memory pressure across the system.
When memory pressure across the system is low, VMMMS makes use of page cache age statistics from Linux’s multi-gen LRU cache manager to create similar distributions in page cache age between ARC++ and the ChromeOS host. This has the effect of creating a fair allowance of page cache for ARC++ and Chrome browser.
When memory pressure across the system is high, both ARC++ and Chrome browser will start killing apps or discarding tabs to free memory. Every low memory app kill and browser tab discard has an associated priority (i.e. a low priority for a background app/tab or a high priority for a focused app/tab). These kill priorities determine which direction the balloon should be adjusted. Low memory balloon adjustments are driven by Android’s low memory killer (LMKD) and by browser tab discard attempts by Chrome browser.
Let’s say Chrome browser is running low on memory.The browser signals that it wants to discard a low priority tab. This signal is routed to VMMMS, which knows that ARC++ was very recently running low on memory and attempted to kill a higher priority app. Because of this, VMMMS knows the current tasks being performed in ARC++ (higher priority app) should be left alone, while the lower priority Chrome tab should be killed.The net effect of this system is that memory is guaranteed to be allocated in such a way to protect the most important user tasks at a given time.
Doze Mode
On physical Android devices, there are a few power-saving mechanisms to limit activity when the device is not in use. One such mechanism is Android’s Doze Mode, which reduces the frequency of periodic background tasks performed by apps and by the OS when the device is not plugged to power. Doze Mode is first triggered by the device having its screen turned off (which happens when power is explicitly turned off, or the display goes dark due to a timeout), and it is an intermediate state preceding Idle mode.
ARC++ being a virtual device working within the confines of its physical ChromeOS host device, did not naturally benefit from Doze Mode because Android can go unused for extended periods of time while the browser is still constantly being used (a very common scenario), while ARC++ is constantly in active state.
Doze Mode for ARC++ aims to fill that gap. We fake a “turn off display” event for ARC++ when it is not used for a while, even if the physical display is still on for ChromeOS. The net effect is that Android will go into Doze Mode, and then into idle mode, while the Chrome browser may still be in use and the screen is still on. This allows us to free more resources for web browsing tasks while Android applications are not being used, and opens the door for power savings.
ARC++ on Demand
ARC++ normally boots immediately after logging in to ChromeOS, allowing users quick access to their Android applications. However, not everyone uses ARC++ regularly and having it running in the background takes away CPU and memory from other ChromeOS tasks.
ARC++ on Demand improves this by looking at what applications are installed on the machine. If a user hasn’t installed any additional Android apps, then ARC++ will not start up when they log in. If later they start a pre-installed Android app or open Google Play to install a new app, then ARC++ on Demand will be deactivated and ARC++ will start up, with a slight delay, and then work as normal. ARC++ on Demand frees up CPU and memory and improves overall device performance while using less power, all while keeping the flexibility of running ARC++ when it is needed.
Since releasing these changes, we’ve seen a number of performance improvements. There’s been a 50% reduction in Chrome tab discards without triggering ARC++ app kills, and we see that users that don’t run ARC++ have on average 15 - 20% power savings and save around 750 MB of memory.
These changes open the door for future power-saving improvements, while raising ARC++ CDD compliance level. We’re excited to have these land and look forward to continuing to improve Android app performance for you.