Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Questions regarding inevitable nature of performance gains and losses of ServiceWorker #1667

Closed
edwardkenfox opened this issue Jan 20, 2023 · 4 comments

Comments

@edwardkenfox
Copy link

edwardkenfox commented Jan 20, 2023

Hi! Apologies in advance for the super lengthy post.

I've been doing some intensive research and experiments how I can make the most out of Service Workers and stumbled upon a couple of performance related questions, and felt the necessity to get some expert inputs. What I'm about to explain here may look like they're not necessarily be relevant to the spec but rather an implementation details, although it still seemed to me that the issues are heavily related to the very nature of Service Worker, thus I've decided to post it here. If they still seem irrelevant after all, perhaps if anyone can point me to somewhere more appropriate that would be extremely helpful.

Q1

Based on what I can confirm, I see that installing a Service Worker that does pretty much nothing would still have some extra end-to-end overhead. (I was using SW Benchmark by @jakearchibald , but could confirm this in my SW as well.) Of course, there's some extra JavaScript code that gets executed, thus the extra overhead is understandable. Although, the actual latency I'm seeing seems a bit too much for an "empty" or "pass-through" handlers, like 30-40ms, and wanted to know if Service Worker was specced or built taking this fact for granted.

More specifically, I can understand that leveraging cache can significantly improve a site's performance when the device is connected to a network with mid-to-low bandwidth/speed, which is absolutely great. But, when the network speed is fast enough (like 100+M/bps) this "pass-through" overhead can not only diminish the performance gain but potentially make it worse than not having any Service Worker code and/or returning data from cache. So, my question is: Was the intension of inventing Service Worker and its capability to serve content from cache to mainly improve performance under mid-to-poor network environments?

Related topics:

Q2

The Cache API (and it's back-end storage: Cache Storage) resides within the Service Worker spec, and it appears to be the de facto storage when using Service Worker for cache purposes storing different resources/responses. Although, I have observed that the storage I/O is pretty significant as large as 10-50ms, and this I/O overhead could greatly offset the performance gain of having the cached data.

This leads me to think that I could just keep everything in-memory of Service Worker and forget about the storage. I am aware that this would have significant impact on the capabilities of what the Service Worker can achieve, for instance losing cached data in the following session. Yet, considering the inevitable overhead of the Cache Storage I/O I'm more leaning towards the idea that there should be something like a on-memory storage API to fully leverage the caches. I personally see in-session user experience is more important than what's carried over across multiple sessions, and wanted to seek advice from experts if there's any room for this to be discussed as part of the spec, or rather a browser specific feature.

If there had been some kind of an architectural and/or spec related decision like "caches should/must be persisted to disk (= Cache Storage)" I'd love to know, if not I'm curious to know your thoughts on this. Or if anyone can point out to me the downsides of the idea to keep things in-memory, that would also be great.

Q3

Based on my thoughts described in Q2, I was curious what would happen when the Service Worker thread uses excessive amount of memory by running the following code:

arr = []; while(1) { arr.push("foo"); }

I see that with Chrome not only the Service Worker thread crashes, but also the parent/client renderer process (the tab) crashes. This must be specific to Chromium's architecture and process model, but I believe this is far from how it should be. I mean, based on my little knowledge, I personally think it's much better to let the Service Worker process/thread crash just by itself without causing the original tab to crash, UX wise and security wise. (I am no security expert, so correct me if I'm wrong.)

My question here is: Is there any room for the spec to define something around what should happen when a Service Worker exhausts its memory, or perhaps a more general scenario of when it stops or crashes? If this is something that I should report to https://bugs.chromium.org/ then I'm happy to do so.


That's all I got to say for now. Kudos to everyone for expanding the capabilities of the web and making this exciting feature happen!

@asutherland
Copy link

  • A1: See https://w3c.github.io/ServiceWorker/#motivations and also https://developer.mozilla.org/en-US/docs/Glossary/Progressive_Enhancement because ServiceWorkers are not intended to be necessary to use a site (although obviously it is possible, though not advisable or commendable, to structure sites in a way that require ServiceWorkers).

  • A2: Specs ideally try to provide implementations as much latitude as possible to optimize, only codifying behavior when necessary to provide consistency in observable behavior and thereby maintaining web compatibility between browsers. A ServiceWorker that tried to explicitly cache things in memory itself would likely be counter-productive as it would defeat immense swathes of existing browser optimizations (the HTTP cache, the ability to store derived byproducts like the JS bytecode cache and WASM compiled representations that can be stored alongside HTTP cache and Cache API entries, the ability to just send file descriptors between processes and memory map things, various shared memory optimizations) and operating system optimizations (disk caches), plus subject itself to significant resource management pressure that would motivate the browser to reboot the ServiceWorker regularly and/or unload pages associated with it.

  • A3: As in A2, the goal is to minimize implementation constraints. The primary spec mechanism that relates to this is the concept of agent clusters. Service Workers (like Shared Workers) do not exist in the same agent cluster as their controlled pages and so can be placed in the same process or a different process. In general, it's probably best for a site to assume that if any of its globals crash, it will take down all of the globals and the tab too. I should also note that, at least in Firefox, which currently does isolate ServiceWorkers in their own processes, we would be likely to mark a ServiceWorker as broken that kept crashing its process or kept using exorbitant amounts of resources and would bypass the ServiceWorker like ctrl-shift-reload is used on subsequent loads.

@edwardkenfox
Copy link
Author

A1

After reading through https://w3c.github.io/ServiceWorker/#motivations , I'm wondering if it means that the original motivations include things like supporting offline contexts and web push, while improving the page's performance is not? I understand the concept of Progressive Enhancement and the fact that building a site where a ServiceWorker's existence is mandatory. What I want to know is: Can we see ServiceWorker as a means to improve site performance?

A2

Understood, thanks a lot for all the details.

A3

Never knew about the concept of agent clusters, will look into it. It seems to be that the way Firefox handles such situation is better than what I have observed in Chrome, but I suppose going back to your point that "the goal is to minimize implementation constrains," it's not a spec's job to decide all those implementation details.

@asutherland
Copy link

A1

  • There will always be a startup overhead cost to a ServiceWorker; this can be partially mitigated by navigation preload creating a racing request to the server.
  • If someone told me their site performance was bad, a ServiceWorker is one of the last things on the list of things I would suggest to them unless their site is explicitly expected to be used in scenarios with bad network connectivity like a transit app for subway riders and profiling demonstrated their problems were due to network flakiness. Alex Russell of Service Workers fame has written a lot in the space of site performance, which is a much larger discussion than just Service Workers, but is discussed in his analyses in that larger context, and I would suggest checking out his extensive writings on the subject.

@edwardkenfox
Copy link
Author

Thanks for the follow up. I will look into the materials and see if I have anything else I want to address. Meanwhile, my original questions had been answered clearly, so I'd like to close the issue. Thank you once again for the thorough answers.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants