Closed Bug 674996 Opened 13 years ago Closed 3 years ago

Use fork() for the content process in XRE_main

Categories

(GeckoView Graveyard :: Sandboxing, enhancement)

enhancement
Not set
normal

Tracking

(Not tracked)

RESOLVED INVALID

People

(Reporter: stechz, Unassigned)

References

Details

We could save some memory, I/O and CPU time by forking our content process by forking in XRE_main before any component registration begins. The content process should immediately suspend itself until EnsureContentProcess is called. This should be fairly easy to do if we didn't have Java in our process by this point already.
Component: General → IPC
Product: Fennec → Core
QA Contact: general → ipc
(Just to be sure, you're not planning on working on this for android, right? It's not going to work there.) I'm a bit skeptical about the potential savings of this. The biggest win would probably be not reading the plugin-container image from disk for exec(), but plugin-container is tiny, ~42KB for an android opt build. We should just readahead it like we do for libs, if the IO shows up in analysis. The only potential memory savings comes from rw pages set up for COW in the child process but never written there. There are probably some of these set up by static initializers that we'd save, but I'm not so sure they'd amount to much. The big chunks of memory, ro pages and text sections, we share anyway. We would definitely save some CPU time from skipping task re-initialization in the kernel needed by exec() and dynamic linking in the child process. I don't have a very good feel for how expensive the latter is, CC'ing taras for thoughts.
Note too that this plan as stated is designed for only one content process. We have hand-wavy plans to make a "zygote"-style pristine content process to fork from. This plan would work with that, in that the pristine process would be the one forked from XRE_main, and then we'd fork that pristine copy again for each actual content process.
The win should be pretty significant. I'm guessing 50-200ms on galaxy s type devices. This also avoids rerunning static initializers again, etc. This should also save a bunch of memory by not having to Copy-on-Write so many pages during runtime linker phase. Additional savings can be had by opening the omnijar and doing any other initialization common to both processes before fork()ing. We can get a ballpark figure on savings from this by setenv()ing PR_Now() in parent process and then comparing that in plugin-container's main() to PR_Now(). Worth trying this out on a couple of different devices before we proceed.
Do we run enough static initializers for them to be a significant cost? I thought glandium fixed that. Don't understand the COW savings you refer to. I forgot about omnijar, common init there sounds promising. Sadly this won't work on android, but sounds like something to try for desktop-linux and mac (and b2g :).
(In reply to comment #1) > (Just to be sure, you're not planning on working on this for android, right? > It's not going to work there.) Are you talking about Java here? This idea is on the assumption that we could implement our intention natively, at least up to XRE_main, so that Java would not be initialized when we fork. > I'm a bit skeptical about the potential savings of this. The biggest win > would probably be not reading the plugin-container image from disk for > exec(), but plugin-container is tiny, ~42KB for an android opt build. We > should just readahead it like we do for libs, if the IO shows up in > analysis. The only potential memory savings comes from rw pages set up for > COW in the child process but never written there. There are probably some > of these set up by static initializers that we'd save, but I'm not so sure > they'd amount to much. The big chunks of memory, ro pages and text > sections, we share anyway. I'm not really worried about plugin-container loading. I thought I had noticed that tMain is still high (actually, even higher than the main process), so I assumed this meant we were reloading libxul.so and once again relocating symbols. (In reply to comment #2) > Note too that this plan as stated is designed for only one content process. > We have hand-wavy plans to make a "zygote"-style pristine content process to > fork from. This plan would work with that, in that the pristine process > would be the one forked from XRE_main, and then we'd fork that pristine copy > again for each actual content process. Yes, I think this idea extends just as well to multiple content processes.
(In reply to comment #5) > (In reply to comment #1) > > (Just to be sure, you're not planning on working on this for android, right? > > It's not going to work there.) > > Are you talking about Java here? This idea is on the assumption that we > could implement our intention natively, at least up to XRE_main, so that > Java would not be initialized when we fork. Yes, I'm talking about the current code in which XRE_main runs on a non-main() java thread. If we could get a real main() on android ... /me wipes tear from eye ... that would make so many things better+possible.
> Yes, I'm talking about the current code in which XRE_main runs on a > non-main() java thread. If we could get a real main() on android ... /me > wipes tear from eye ... that would make so many things better+possible. Yay! I have been told it is possible (but a lot of work). I'd be interested to hear in how this would help otherwise to mount an argument in bug 673259.
After talking with Brad, it looks like we still need the Java VM in the main process even if we did implement the intention natively. Closing for now.
Status: NEW → RESOLVED
Closed: 13 years ago
Resolution: --- → INVALID
We don't need the JVM in XRE_main(), and we certainly don't need it in subprocesses. This might still be a valid optimization, don't throw it out yet ;).
Status: RESOLVED → REOPENED
Resolution: INVALID → ---
There's at least 100ms to be saved on a Nexus S by avoiding relocations (bug 651890). fork()ing instead of fork()+exec() would save that freely, though I was thinking about avoiding these relocations at the linker level.
(In reply to comment #10) > There's at least 100ms to be saved on a Nexus S by avoiding relocations (bug > 651890). That's 100ms for relocations + static initializers, by the way.

Bug 1470591 is going to do this on desktop (mainly to save memory rather than time). As for Android, I don't think this is possible with how we're doing things today but I'm not an expert there.

Type: defect → enhancement
Component: IPC → Widget: Android
See Also: → 1470591

Moving all open Core::Widget: Android bugs to GeckoView::General (then the triage owner of GeckoView will decide which ones are valuable and which ones should be closed).

Component: Widget: Android → General
Product: Core → GeckoView
Version: Trunk → unspecified

Not applicable to GeckoView

Status: REOPENED → RESOLVED
Closed: 13 years ago3 years ago
Resolution: --- → INVALID

Moving content process management bugs to the new GeckoView::Sandboxing component.

Component: General → Sandboxing
Product: GeckoView → GeckoView Graveyard
You need to log in before you can comment on or make changes to this bug.