Bug 224015 - Have the ServiceWorker process hold on to a file mapped version of the service worker scripts to save dirty memory
Summary: Have the ServiceWorker process hold on to a file mapped version of the servic...
Status: RESOLVED FIXED
Alias: None
Product: WebKit
Classification: Unclassified
Component: Service Workers (show other bugs)
Version: WebKit Nightly Build
Hardware: Unspecified Unspecified
: P2 Normal
Assignee: Chris Dumez
URL:
Keywords: InRadar
Depends on:
Blocks: 224092
  Show dependency treegraph
 
Reported: 2021-03-31 13:54 PDT by Chris Dumez
Modified: 2021-04-02 13:24 PDT (History)
10 users (show)

See Also:


Attachments
Patch (23.74 KB, patch)
2021-03-31 14:06 PDT, Chris Dumez
no flags Details | Formatted Diff | Diff
Patch (23.74 KB, patch)
2021-03-31 18:25 PDT, Chris Dumez
ews-feeder: commit-queue-
Details | Formatted Diff | Diff
Patch (23.81 KB, patch)
2021-03-31 18:38 PDT, Chris Dumez
ews-feeder: commit-queue-
Details | Formatted Diff | Diff
Patch (37.60 KB, patch)
2021-04-01 09:51 PDT, Chris Dumez
no flags Details | Formatted Diff | Diff
Patch (37.59 KB, patch)
2021-04-01 12:10 PDT, Chris Dumez
no flags Details | Formatted Diff | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Chris Dumez 2021-03-31 13:54:58 PDT
Once saved to disk, then mmap'd data of service worker scripts back to the ServiceWorker process, in order to save dirty memory. This is similar to what we do in the network cache implementation.
Comment 1 Chris Dumez 2021-03-31 14:06:12 PDT
Created attachment 424818 [details]
Patch
Comment 2 Chris Dumez 2021-03-31 18:25:32 PDT
Created attachment 424855 [details]
Patch
Comment 3 Chris Dumez 2021-03-31 18:38:04 PDT
Created attachment 424857 [details]
Patch
Comment 4 Chris Dumez 2021-04-01 09:24:06 PDT
<rdar://75637679>
Comment 5 Darin Adler 2021-04-01 09:24:22 PDT
Comment on attachment 424857 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=424857&action=review

> Source/WebCore/platform/SharedBuffer.cpp:224
> +    unsigned count = 0;
> +    for (auto it = begin(); it != end(); ++it)
> +        ++count;
> +    return count;

This can be written like this:

    return std::count(begin(), end());

But also, not sure we want this function. I think hasOneSegment would be a better function to add. It would be something like this:

    auto it = begin();
    return it != end() && ++it == end();

> Source/WebKit/NetworkProcess/ServiceWorker/WebSWServerToContextConnection.cpp:117
> +        if (buffer.numberOfSegments() != 1)

This is an inefficient way to check If there is exactly one segment if we have a buffer with a lot segments in it!
Comment 6 Chris Dumez 2021-04-01 09:26:03 PDT
(In reply to Darin Adler from comment #5)
> Comment on attachment 424857 [details]
> Patch
> 
> View in context:
> https://bugs.webkit.org/attachment.cgi?id=424857&action=review
> 
> > Source/WebCore/platform/SharedBuffer.cpp:224
> > +    unsigned count = 0;
> > +    for (auto it = begin(); it != end(); ++it)
> > +        ++count;
> > +    return count;
> 
> This can be written like this:
> 
>     return std::count(begin(), end());
> 
> But also, not sure we want this function. I think hasOneSegment would be a
> better function to add. It would be something like this:
> 
>     auto it = begin();
>     return it != end() && ++it == end();
> 
> > Source/WebKit/NetworkProcess/ServiceWorker/WebSWServerToContextConnection.cpp:117
> > +        if (buffer.numberOfSegments() != 1)
> 
> This is an inefficient way to check If there is exactly one segment if we
> have a buffer with a lot segments in it!

Ok. Will address. Please don't review this iteration further. This patch is very outdated and I will upload a fresh version shortly.
Comment 7 Darin Adler 2021-04-01 09:27:26 PDT
(In reply to Chris Dumez from comment #6)
> Please don't review this iteration further. This patch is
> very outdated and I will upload a fresh version shortly.

No worries, I won’t.
Comment 8 Chris Dumez 2021-04-01 09:51:07 PDT
Created attachment 424908 [details]
Patch
Comment 9 Geoffrey Garen 2021-04-01 12:02:14 PDT
Comment on attachment 424908 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=424908&action=review

r=me

> Source/WebCore/ChangeLog:13
> +        scripts to the ServiceWorker processes as ShareableResource handles so that the dirty memory usage

so that => in order to reduce

> Source/WebCore/ChangeLog:16
> +        No new tests, no Web-facing behavior change, just a decrease dirty memory use in the ServiceWorker

decrease => decrease in
Comment 10 Geoffrey Garen 2021-04-01 12:03:11 PDT
Comment on attachment 424908 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=424908&action=review

> Source/WebCore/ChangeLog:19
> +        memory usage goes from ~440MB to ~230MB in both the cold and warm cases ("Cold" meaning that the

I wonder if, in the cold case, executing the service worker script causes JavaScriptCore to retain a large dirty memory string. Maybe that explains the remaining 230MB?
Comment 11 Chris Dumez 2021-04-01 12:05:18 PDT
(In reply to Geoffrey Garen from comment #10)
> Comment on attachment 424908 [details]
> Patch
> 
> View in context:
> https://bugs.webkit.org/attachment.cgi?id=424908&action=review
> 
> > Source/WebCore/ChangeLog:19
> > +        memory usage goes from ~440MB to ~230MB in both the cold and warm cases ("Cold" meaning that the
> 
> I wonder if, in the cold case, executing the service worker script causes
> JavaScriptCore to retain a large dirty memory string. Maybe that explains
> the remaining 230MB?

230MB remain in the WebProcess in both the cold and warm cases. This seems to indicate both 100MB scripts are still kept in memory in the WebProcess in one place. Looking at the code, I *think* it must in JavaScriptCore indeed. I can try and find out why in a follow-up.
Comment 12 Chris Dumez 2021-04-01 12:10:25 PDT
Created attachment 424927 [details]
Patch
Comment 13 Darin Adler 2021-04-01 12:12:27 PDT
Maybe a garbage-collectable string that just hasn’t been collected yet?
Comment 14 Chris Dumez 2021-04-01 12:13:36 PDT
(In reply to Darin Adler from comment #13)
> Maybe a garbage-collectable string that just hasn’t been collected yet?

Maybe but I did send a memory pressure warning before collecting memory measurements. The memory pressure warning *should* have triggered a sync GC I think.
Comment 15 Chris Dumez 2021-04-01 12:15:06 PDT
(In reply to Chris Dumez from comment #14)
> (In reply to Darin Adler from comment #13)
> > Maybe a garbage-collectable string that just hasn’t been collected yet?
> 
> Maybe but I did send a memory pressure warning before collecting memory
> measurements. The memory pressure warning *should* have triggered a sync GC
> I think.

Note that the scripts I used are very simple:
large.js:
```
importScripts('large-sub.js');
a = 1;
/* a 100MB comment */
```

large-sub.js:
```
b = 2;
/* a 100 MB comment */
```
Comment 16 EWS 2021-04-01 13:05:54 PDT
Committed r275375: <https://commits.webkit.org/r275375>

All reviewed patches have been landed. Closing bug and clearing flags on attachment 424927 [details].
Comment 17 Chris Dumez 2021-04-02 13:24:04 PDT
(In reply to Darin Adler from comment #13)
> Maybe a garbage-collectable string that just hasn’t been collected yet?

Turns out we were not clearing the JS code cache or doing GC in worker threads on memory pressure. I followed up in Bug 224110.