New issue
Advanced search Search tips
Note: Color blocks (like or ) mean that a user may not be available. Tooltip shows the reason.

Issue 718199 link

Starred by 2 users

Issue metadata

Status: Available
Owner: ----
Cc:
Components:
EstimatedDays: ----
NextAction: ----
OS: Android
Pri: 2
Type: Bug

Blocking:
issue 735799
issue 740209



Sign in to add a comment

NTP snippet creates short-lived renderer process

Project Member Reported by dskiba@chromium.org, May 3 2017

Issue description

When Chrome is started on Android it seems to create short-lived renderer process. Here is what I see on startup if I poll chrome processes with "while true; do adb shell ps | grep chrome; echo ''; sleep 1; done":

u0_a86        5991   375 1119660  33308 0            b1445fc8 R com.google.android.apps.chrome

u0_a86        5991   375 1311960  74544 0            92d494d0 R com.google.android.apps.chrome
u0_i23        6020   375 1116852  27804 SyS_epoll_wait b3cd0154 S com.google.android.apps.chrome:sandboxed_process0

u0_a86        5991   375 1353016 104068 0            b3c9ff08 R com.google.android.apps.chrome
u0_i23        6020   375 1394148  50384 SyS_epoll_wait b3cd0154 S com.google.android.apps.chrome:sandboxed_process0
u0_i24        6086   375 1210204  37456 SyS_epoll_wait b3cd0154 S com.google.android.apps.chrome:sandboxed_process1

u0_a86        5991   375 1350916 104088 SyS_epoll_wait b3cd0154 S com.google.android.apps.chrome
u0_i23        6020   375 1392100  50448 SyS_epoll_wait b3cd0154 S com.google.android.apps.chrome:sandboxed_process0
u0_i24        6086   375 1210204  37456 SyS_epoll_wait b3cd0154 S com.google.android.apps.chrome:sandboxed_process1

u0_a86        5991   375 1351940 104748 SyS_epoll_wait b3cd0154 S com.google.android.apps.chrome
u0_i23        6020   375 1392100  50448 SyS_epoll_wait b3cd0154 S com.google.android.apps.chrome:sandboxed_process0
u0_i24        6086   375 1210204  37456 SyS_epoll_wait b3cd0154 S com.google.android.apps.chrome:sandboxed_process1

u0_a86        5991   375 1351940 104412 SyS_epoll_wait b3cd0154 S com.google.android.apps.chrome
u0_i23        6020   375 1392100  50468 SyS_epoll_wait b3cd0154 S com.google.android.apps.chrome:sandboxed_process0
u0_i24        6086   375 1210204  37456 SyS_epoll_wait b3cd0154 S com.google.android.apps.chrome:sandboxed_process1

u0_a86        5991   375 1351876 104660 SyS_epoll_wait b3cd0154 S com.google.android.apps.chrome
u0_i23        6020   375 1392100  50676 SyS_epoll_wait b3cd0154 S com.google.android.apps.chrome:sandboxed_process0

u0_a86        5991   375 1352928 104792 SyS_epoll_wait b3cd0154 S com.google.android.apps.chrome
u0_i23        6020   375 1392100  50676 SyS_epoll_wait b3cd0154 S com.google.android.apps.chrome:sandboxed_process0

u0_a86        5991   375 1352928 104792 SyS_epoll_wait b3cd0154 S com.google.android.apps.chrome
u0_i23        6020   375 1392100  50676 SyS_epoll_wait b3cd0154 S com.google.android.apps.chrome:sandboxed_process0

I.e. temporary chrome:sandboxed_process1 lived for ~5 seconds.

If I scroll down a bit to reveal next NTP snippet, temporary process is created again:

u0_a86        5991   375 1346480 104724 SyS_epoll_wait b3cd0154 S com.google.android.apps.chrome
u0_i23        6020   375 1392100  50636 SyS_epoll_wait b3cd0154 S com.google.android.apps.chrome:sandboxed_process0

u0_a86        5991   375 1346480 105208 0            b3cd0294 R com.google.android.apps.chrome
u0_i23        6020   375 1392100  50636 SyS_epoll_wait b3cd0154 S com.google.android.apps.chrome:sandboxed_process0

u0_a86        5991   375 1346544 106256 SyS_epoll_wait b3cd0154 S com.google.android.apps.chrome
u0_i23        6020   375 1392100  50636 SyS_epoll_wait b3cd0154 S com.google.android.apps.chrome:sandboxed_process0
u0_i25        6216   375 1210204  37608 SyS_epoll_wait b3cd0154 S com.google.android.apps.chrome:sandboxed_process2

u0_a86        5991   375 1346544 106256 SyS_epoll_wait b3cd0154 S com.google.android.apps.chrome
u0_i23        6020   375 1392100  50636 SyS_epoll_wait b3cd0154 S com.google.android.apps.chrome:sandboxed_process0
u0_i25        6216   375 1210204  37608 SyS_epoll_wait b3cd0154 S com.google.android.apps.chrome:sandboxed_process2

u0_a86        5991   375 1346544 106256 SyS_epoll_wait b3cd0154 S com.google.android.apps.chrome
u0_i23        6020   375 1392100  50636 SyS_epoll_wait b3cd0154 S com.google.android.apps.chrome:sandboxed_process0
u0_i25        6216   375 1210204  37608 SyS_epoll_wait b3cd0154 S com.google.android.apps.chrome:sandboxed_process2

u0_a86        5991   375 1346544 106256 SyS_epoll_wait b3cd0154 S com.google.android.apps.chrome
u0_i23        6020   375 1392100  50636 SyS_epoll_wait b3cd0154 S com.google.android.apps.chrome:sandboxed_process0
u0_i25        6216   375 1210204  37608 SyS_epoll_wait b3cd0154 S com.google.android.apps.chrome:sandboxed_process2

u0_a86        5991   375 1346480 105752 SyS_epoll_wait b3cd0154 S com.google.android.apps.chrome
u0_i23        6020   375 1392100  50636 SyS_epoll_wait b3cd0154 S com.google.android.apps.chrome:sandboxed_process0

If I open NTP page, then the temporary renderer is created again, even though the top snippet ends up being is exactly the same as on the current page:

u0_a86        5991   375 1345436 105504 SyS_epoll_wait b3cd0154 S com.google.android.apps.chrome
u0_i23        6020   375 1392100  50636 SyS_epoll_wait b3cd0154 S com.google.android.apps.chrome:sandboxed_process0

u0_a86        5991   375 1345436 106136 SyS_epoll_wait b3cd0154 S com.google.android.apps.chrome
u0_i23        6020   375 1392100  50636 SyS_epoll_wait b3cd0154 S com.google.android.apps.chrome:sandboxed_process0

u0_a86        5991   375 1359992 111412 0            b3c9fef8 R com.google.android.apps.chrome
u0_i23        6020   375 1391972  50888 SyS_epoll_wait b3cd0154 S com.google.android.apps.chrome:sandboxed_process0
u0_i26        6361   375 1396964  50948 SyS_epoll_wait b3cd0154 S com.google.android.apps.chrome:sandboxed_process3
u0_i27        6380   375 1210204  37536 SyS_epoll_wait b3cd0154 S com.google.android.apps.chrome:sandboxed_process4

u0_a86        5991   375 1358296 110324 SyS_epoll_wait b3cd0154 S com.google.android.apps.chrome
u0_i23        6020   375 1391972  50888 SyS_epoll_wait b3cd0154 S com.google.android.apps.chrome:sandboxed_process0
u0_i26        6361   375 1396196  50968 SyS_epoll_wait b3cd0154 S com.google.android.apps.chrome:sandboxed_process3
u0_i27        6380   375 1210204  37708 SyS_epoll_wait b3cd0154 S com.google.android.apps.chrome:sandboxed_process4

u0_a86        5991   375 1358296 110324 SyS_epoll_wait b3cd0154 S com.google.android.apps.chrome
u0_i23        6020   375 1391972  50888 SyS_epoll_wait b3cd0154 S com.google.android.apps.chrome:sandboxed_process0
u0_i26        6361   375 1396196  50968 SyS_epoll_wait b3cd0154 S com.google.android.apps.chrome:sandboxed_process3
u0_i27        6380   375 1210204  37708 SyS_epoll_wait b3cd0154 S com.google.android.apps.chrome:sandboxed_process4

u0_a86        5991   375 1353944 110056 SyS_epoll_wait b3cd0154 S com.google.android.apps.chrome
u0_i23        6020   375 1391972  50888 SyS_epoll_wait b3cd0154 S com.google.android.apps.chrome:sandboxed_process0
u0_i26        6361   375 1392100  51168 SyS_epoll_wait b3cd0154 S com.google.android.apps.chrome:sandboxed_process3
u0_i27        6380   375 1210204  37708 SyS_epoll_wait b3cd0154 S com.google.android.apps.chrome:sandboxed_process4

u0_a86        5991   375 1353880 110164 SyS_epoll_wait b3cd0154 S com.google.android.apps.chrome
u0_i23        6020   375 1391952  50768 SyS_epoll_wait b3cd0154 S com.google.android.apps.chrome:sandboxed_process0
u0_i26        6361   375 1392100  51184 SyS_epoll_wait b3cd0154 S com.google.android.apps.chrome:sandboxed_process3


Is there any way we can avoid creating temporary renderers on low-end devices?
 
Labels: -LowEnd LowMemory
It may be a utility process rather than a renderer process. We should check.
Cc: mvanouwe...@chromium.org
Are they actually different on Android?

Also +Michael who has been looking into this.
(Oh, forgot to mention, for the sake of completeness: this is probably image loading, which happens in native code and probably spawns a utility process)
I'm looking into the decoder service, which is for image decoding only. If the mystery process reported in this bug also performs network requests, that would need many more dependencies than just decoding. So I'm not sure yet whether the decoder service can help here.
Can't we use warmup renderer for image decoding?

(I'll check whether that short-lived process is a utility process or not.)
Blocking: 740209
OK, so the utility process in question is started for "Data Decoder Service" mojo service, which decodes images. That service is among several other out of process services configured by ServiceManagerContext::ServiceManagerContext().

I think we need to run this service in-process, when we're in Monochrome that is not multiprocess.
Cc: roc...@chromium.org aelias@chromium.org jam@chromium.org torne@chromium.org
Folks, please give your input on making "Data Decoder Service" in-process in one specific configuration.


Context: both new tab page and Chrome Home (its successor) have snippet stories that feature images. Those images are decoded using "Data Decoder Service" mojo service, which spawns a utility process. On 512 devices spawning that process makes Chrome Home janky, and increases overall memory pressure, leading to even more memory thrashing and jank. At the same time Monochrome is not multiprocess in that configuration (see [1]), and GPU process runs inside browser process (see [2]).


Proposal: make "Data Decoder Service" in-process in that exact configuration: Monochrome && !multiprocess WebView. The idea is that since WebView is already not multiprocess, we're not gaining much security by using out-of-process services in Monochrome itself, while regressing performance and usability.


Stretch: audit and disable more (potentially all) out-of-process mojo services in that configuration.



[1] https://googleplex-android-review.git.corp.google.com/#/c/platform/frameworks/base/+/2377647/
[2] https://cs.chromium.org/chromium/src/content/browser/android/content_startup_flags.cc?l=57
Seems reasonable to me, and in general it should be painless to configure a
service to run in- or out-of-process based on build configuration.

One concern I'd have with data_decoder specifically is that all our image
decoding routines are defined in Blink, and so data_decoder actually has to
initialize Blink on startup. Initializing Blink in the browser process
seems questionable to me.
Hm, Chrome itself still uses multi-process rendering on low-end devices though, right? Not sure whether that changes the security equation.

What we should also be wary of is OOM crashes: if image decoding happens in a separate process, that process can run out of memory and crash without taking the browser down, but that won't work if it's done in the browser process.

And lastly: Specifically for the use case of content suggestions, if we want to decode images in the browser process, we could simply use BitmapFactory to avoid initialization Blink and copying the bitmap across the JNI boundary.
It seems really weird to make Chrome's behaviour conditional on WebView's configuration and I don't think it's a reasonable assertion that if WebView isn't multiprocess then Chrome doesn't gain any security from out-of-process services - if that were the case then Chrome shouldn't use them on any OS version prior to O at all, since WebView was always single-process before :)

WebView multiprocess is currently disabled for lowram 32-bit devices. If you want to disable the out-of-process services for Chrome on lowram 32-bit devices as well then that seems like a reasonable choice, but directly tying it to webview or arguing for it because of webview's security level seems wrong.
Thanks for your replies, guys!

I see that we have two paths to take:

1. Make "Data Decoder Service" in-process on low-end devices (regardless of webview multiprocess status). Concerns here: (a) OOMs taking down browser process, (b) cost of Blink initialization.

2. Decode content suggestions bitmaps using BitmapFactory, avoiding decoder service completely. I guess OOM is less of a concern here because content suggestions are controlled by us. Bonus here is that we'll avoid cost of JNI.

I'm leaning towards #2, but I'm curious about other decoder service uses. Do we have any idea (UMAs) how frequently decoder services (or any other utility process services) are used during normal user session?


Finally, some directed questions:

bauerb@ how hard it will be to switch content suggestions to use BitmapFactory on low-end devices only?

rockot@ are we running one service per utility process, or can there be many? I guess when a renderer requests decoder service and it's not there, a new utility process is created? Is it possible / makes sense to run decoder service in the renderer itself?


BTW, on 512 Android Go device we spend 200ms to load native library, and only 10ms on 3 data_decoder::mojom::ImageDecoder calls. 
Blocking: 735799
Running data_decoder in a renderer process is trickier. We would have to pick a renderer process to use, and then we have to rework render process lifetime control such that e.g. navigation or something doesn't rip a data_decoder instance out from under its client by killing the render that's running it.

With a small amount of refactoring it's possible to share a single utility process for multiple service instances. Right now we don't do that, but I'm not convinced that this actually matters or that it would address the issue at hand.

data_decoder is designated as a singleton service, meaning we will have at most one instance of it alive at any time. If an instance is already running and a new client tries connecting to data_decoder, its connection will be routed to the existing instance.

data_decoder also keeps itself alive for 5 seconds after its last client disconnects, to account for cases where multiple independent decode requests are issued in succession. I would be surprised to learn that this behavior is no longer working.
Cc: finnur@chromium.org
Yeah, the image decoder definitely stays alive for 5s while scrolling through content suggestions.

Dmitry: switching content suggestions to use BitmapFactory would not be incredibly complicated (although we might not want to do that in the SnippetsBridge, so that it can be a pure JNI glue class). OOM might still be a concern though (even if we assume the files aren't maliciouslow-end devices still run out of memory easily...), and even though we get the article thumbnails from Google servers, that's still a different machine, which we usually treat as untrusted.

Also +Finnur, who has dealt with similar things for the image picker.
Cc: bever...@google.com
Adding Peter, who's also been involved in the java version of the image decoder.

Comment 18 by peter@chromium.org, Aug 17 2017

Cc: -bever...@google.com peter@chromium.org

Comment 19 by pasko@google.com, Aug 17 2017

Cc: pasko@chromium.org
Labels: -Pri-3 Pri-2
Labels: zine-triaged
Status: Available (was: Untriaged)
Cc: twelling...@chromium.org dskiba@chromium.org tedc...@chromium.org
 Issue 760697  has been merged into this issue.
Cc: mdjones@chromium.org
Cc: creis@chromium.org
Hey Charlie, you mentioned earlier that each NTP has a hidden renderer for about:blank, for the first page load in the tab. Do you think there is a way we could use that process to decode images shown on the NTP? (See also comment #15).

Comment 24 by creis@chromium.org, Sep 29 2017

Comment #23: Caveat: My knowledge of that is several years old, but I'll assume that about:blank renderer still exists.  :)

You may be able to decode images in that renderer, though rockot@'s concerns in comment #15 do seem relevant.  (It may be complex to keep it alive properly, and the RPH code is already complex due to navigations + service workers + other workers.)  Maybe that could be made to work, though.

I'll point out that this would probably need to mark the renderer process as used in some way, since sites that require dedicated processes wouldn't be able to reuse it anymore.  Such sites doesn't exist yet on Android, but we're starting to ship the first cases of it on desktop.
Project Member

Comment 25 by sheriffbot@chromium.org, Oct 1

Labels: Hotlist-Recharge-Cold
Status: Untriaged (was: Available)
This issue has been Available for over a year. If it's no longer important or seems unlikely to be fixed, please consider closing it out. If it is important, please re-triage the issue.

Sorry for the inconvenience if the bug really should have been left as Available.

For more details visit https://www.chromium.org/issue-tracking/autotriage - Your friendly Sheriffbot
Cc: gangwu@chromium.org fgor...@chromium.org
Status: Available (was: Untriaged)
Cc: -roc...@chromium.org rockot@google.com

Sign in to add a comment