Bug 227376 - [GPU Process] Canvas drawing never releases any fonts
Summary: [GPU Process] Canvas drawing never releases any fonts
Status: RESOLVED FIXED
Alias: None
Product: WebKit
Classification: Unclassified
Component: Canvas (show other bugs)
Version: WebKit Nightly Build
Hardware: Unspecified Unspecified
: P2 Normal
Assignee: Myles C. Maxfield
URL:
Keywords: InRadar
Depends on:
Blocks:
 
Reported: 2021-06-24 14:00 PDT by Said Abou-Hallawa
Modified: 2021-07-13 16:47 PDT (History)
8 users (show)

See Also:


Attachments
Patch (5.05 KB, patch)
2021-06-25 16:50 PDT, Myles C. Maxfield
no flags Details | Formatted Diff | Diff
Patch (5.49 KB, patch)
2021-07-06 21:15 PDT, Myles C. Maxfield
no flags Details | Formatted Diff | Diff
Patch (5.37 KB, patch)
2021-07-07 15:19 PDT, Myles C. Maxfield
no flags Details | Formatted Diff | Diff
Patch (5.71 KB, patch)
2021-07-09 13:13 PDT, Myles C. Maxfield
no flags Details | Formatted Diff | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Said Abou-Hallawa 2021-06-24 14:00:44 PDT
In this function 'unusedFontCount' is always equal to zero because m_fontIdentifierToLastRenderingUpdateVersionMap.size() is always equal to m_numberOfFontsUsedInCurrentRenderingUpdate. In other words all the cached fonts are always considered be used by the current RenderingUpdate.

So this function makes an early return through the if-statement:

    if (unusedFontCount < minimumFractionOfUnusedFontCountToTriggerRemoval * totalFontCount && unusedFontCount <= maximumUnusedFontCountToSkipRemoval)
        return;

except in one case which is totalFontCount == 0. In this case, the body of this function will be executed but it will do nothing because m_fontIdentifierToLastRenderingUpdateVersionMap is empty.

This means all the fonts are cached always in GPUP. They are removed only under memory pressure through WebPage::releaseMemory() which calls RemoteResourceCacheProxy::releaseMemory().
Comment 1 Radar WebKit Bug Importer 2021-06-24 14:01:41 PDT
<rdar://problem/79741186>
Comment 2 Myles C. Maxfield 2021-06-25 16:28:53 PDT
This came from https://bugs.webkit.org/show_bug.cgi?id=227229
Comment 3 Myles C. Maxfield 2021-06-25 16:50:49 PDT
Created attachment 432314 [details]
Patch
Comment 4 Myles C. Maxfield 2021-06-25 17:00:51 PDT
Comment on attachment 432314 [details]
Patch

Getting the same crashes that appeared in https://bugs.webkit.org/show_bug.cgi?id=227229
Comment 5 Myles C. Maxfield 2021-06-25 17:23:11 PDT
Can reproduce the crash with:

run-webkit-tests --debug --no-retry --child-processes=1 --verbose fast/canvas/2d.fillText.gradient.html fast/canvas/2d.getPath.modification.html
Comment 6 Myles C. Maxfield 2021-06-25 17:25:22 PDT
I can reproduce a crash (which may be a different crash) with this: DYLD_FRAMEWORK_PATH=/Users/mmaxfield/Build/Products/Debug ~/Build/Products/Debug/WebKitTestRunner "file:///Users/mmaxfield/src/WebKit/OpenSource/LayoutTests/fast/canvas/2d.fillText.gradient.html" "file:///Users/mmaxfield/src/WebKit/OpenSource/LayoutTests/fast/canvas/2d.getPath.modification.html"
Comment 7 Myles C. Maxfield 2021-06-25 18:39:49 PDT
My theory is that the web process is sending the releaseRemoteResource() message, and then quitting, then a new web process starts up (for the second test, because it has <!-- webkit-test-runner [ InspectorAdditionsEnabled=true ] -->) it creates a new context, and somehow the old message is being delivered to the new context. The new context says "well I don't have any fonts cached with ID 19" and hits the ASSERT_NOT_REACHED().

If this theory is correct, this is real bad.
Comment 8 Myles C. Maxfield 2021-06-25 19:12:29 PDT
I think my theory is confirmed. From the point of view of the GPU Process, we see a RemoteRenderingBackend being created with destinationID 16, then it's destroyed, then we see another RemoteRenderingBackend being created with destinationID 16.
Comment 9 Myles C. Maxfield 2021-07-06 21:15:06 PDT
Created attachment 433007 [details]
Patch
Comment 10 Simon Fraser (smfr) 2021-07-06 21:27:51 PDT
Comment on attachment 433007 [details]
Patch

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

> Source/WebKit/WebProcess/GPU/graphics/RemoteResourceCacheProxy.cpp:152
> +    if (unusedFontCount < minimumFractionOfUnusedFontCountToTriggerRemoval * totalFontCount && unusedFontCount <= maximumUnusedFontCountToSkipRemoval) {
> +        prepareForNextRenderingUpdate();

It would be clearer to move all the font releasing code into a new function, so that this early return is less confusing. It would be too easy to add code below that is not font related.
Comment 11 Myles C. Maxfield 2021-07-07 15:19:04 PDT
Created attachment 433083 [details]
Patch
Comment 12 Said Abou-Hallawa 2021-07-09 13:01:51 PDT
Comment on attachment 433083 [details]
Patch

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

Do we need to change RemoteResourceCacheProxy::cacheFont()? See your comment about it in https://bugs.webkit.org/show_bug.cgi?id=227229#c3 and consider when m_currentRenderingUpdateVersion is zero?

> Source/WebKit/WebProcess/GPU/graphics/RemoteResourceCacheProxy.cpp:152
>      if (unusedFontCount < minimumFractionOfUnusedFontCountToTriggerRemoval * totalFontCount && unusedFontCount <= maximumUnusedFontCountToSkipRemoval)
>          return;

Do we need to change this if-statement or change maximumUnusedFontCountToSkipRemoval from being zero?
Comment 13 Myles C. Maxfield 2021-07-09 13:09:28 PDT
(In reply to Said Abou-Hallawa from comment #12)
> Comment on attachment 433083 [details]
> Patch
> 
> View in context:
> https://bugs.webkit.org/attachment.cgi?id=433083&action=review
> 
> Do we need to change RemoteResourceCacheProxy::cacheFont()? See your comment
> about it in https://bugs.webkit.org/show_bug.cgi?id=227229#c3 and consider
> when m_currentRenderingUpdateVersion is zero?

Nope, because this patch doesn't reset m_currentRenderingUpdateVersion to zero. m_currentRenderingUpdateVersion is a uint64_t so we aren't in danger of it overflowing.
Comment 14 Myles C. Maxfield 2021-07-09 13:10:21 PDT
Comment on attachment 433083 [details]
Patch

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

>> Source/WebKit/WebProcess/GPU/graphics/RemoteResourceCacheProxy.cpp:152
>>          return;
> 
> Do we need to change this if-statement or change maximumUnusedFontCountToSkipRemoval from being zero?

Good idea. I'll upload a new patch.
Comment 15 Myles C. Maxfield 2021-07-09 13:13:27 PDT
Created attachment 433236 [details]
Patch
Comment 16 Said Abou-Hallawa 2021-07-09 15:00:47 PDT
(In reply to Myles C. Maxfield from comment #13)
> (In reply to Said Abou-Hallawa from comment #12)
> > Comment on attachment 433083 [details]
> > Patch
> > 
> > View in context:
> > https://bugs.webkit.org/attachment.cgi?id=433083&action=review
> > 
> > Do we need to change RemoteResourceCacheProxy::cacheFont()? See your comment
> > about it in https://bugs.webkit.org/show_bug.cgi?id=227229#c3 and consider
> > when m_currentRenderingUpdateVersion is zero?
> 
> Nope, because this patch doesn't reset m_currentRenderingUpdateVersion to
> zero. m_currentRenderingUpdateVersion is a uint64_t so we aren't in danger
> of it overflowing.

I just realized we initialize m_currentRenderingUpdateVersion with { 1 }. My question was based on the assumption that it is initialized with { 0 }.
Comment 17 EWS 2021-07-10 09:56:44 PDT
Committed r279806 (239570@main): <https://commits.webkit.org/239570@main>

All reviewed patches have been landed. Closing bug and clearing flags on attachment 433236 [details].
Comment 18 Truitt Savell 2021-07-13 16:47:46 PDT
It looks like the changes in https://trac.webkit.org/changeset/279806/webkit

Broke two tests:
inspector/canvas/recording-webgl-snapshots.html
inspector/canvas/requestClientNodes-css.html

History:
https://results.webkit.org/?suite=layout-tests&suite=layout-tests&test=inspector%2Fcanvas%2Frecording-webgl-snapshots.html&test=inspector%2Fcanvas%2FrequestClientNodes-css.html

tracking in https://bugs.webkit.org/show_bug.cgi?id=227929