Changeset 237735 in webkit


Ignore:
Timestamp:
Nov 2, 2018 8:59:23 AM (5 years ago)
Author:
Chris Dumez
Message:

[PSON] Reuse SuspendedPages' process when possible, for performance
https://bugs.webkit.org/show_bug.cgi?id=191166

Reviewed by Geoffrey Garen.

Source/WebKit:

When process-swapping check if there is an existing SuspendedPage for the domain we're going to.
If there is, use this SuspendedPage's process for the navigation instead of a fresh new process.
This change should be beneficial for performance as it:

  • Avoids spinning up a new process (CPU & memory cost)
  • Likely better leverages caches since this process already loaded this domain in the past

Due to current limitations, using a SuspendedPage's proxy may consume the SuspendedPage, which
means that it can no longer be used for PageCache on history navigations. We need to do this when
the SuspendedPageProxy in question was created for the current WebPageProxy because:

  • This SuspendedPageProxy's process already has a suspended WebPage with this WebPageProxy's pageID

and

  • We do not currently support having more than one WebPage with a given pageID within a single WebProcess.
  • UIProcess/SuspendedPageProxy.cpp:

(WebKit::SuspendedPageProxy::SuspendedPageProxy):

  • UIProcess/SuspendedPageProxy.h:
  • UIProcess/WebProcessPool.cpp:

(WebKit::WebProcessPool::processForNavigationInternal):

Tools:

Add API test coverage.

  • TestWebKitAPI/Tests/WebKitCocoa/ProcessSwapOnNavigation.mm:
Location:
trunk
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebKit/ChangeLog

    r237714 r237735  
     12018-11-02  Chris Dumez  <cdumez@apple.com>
     2
     3        [PSON] Reuse SuspendedPages' process when possible, for performance
     4        https://bugs.webkit.org/show_bug.cgi?id=191166
     5
     6        Reviewed by Geoffrey Garen.
     7
     8        When process-swapping check if there is an existing SuspendedPage for the domain we're going to.
     9        If there is, use this SuspendedPage's process for the navigation instead of a fresh new process.
     10        This change should be beneficial for performance as it:
     11        - Avoids spinning up a new process (CPU & memory cost)
     12        - Likely better leverages caches since this process already loaded this domain in the past
     13
     14        Due to current limitations, using a SuspendedPage's proxy may consume the SuspendedPage, which
     15        means that it can no longer be used for PageCache on history navigations. We need to do this when
     16        the SuspendedPageProxy in question was created for the current WebPageProxy because:
     17        - This SuspendedPageProxy's process already has a suspended WebPage with this WebPageProxy's pageID
     18        and
     19        - We do not currently support having more than one WebPage with a given pageID within a single
     20          WebProcess.
     21
     22        * UIProcess/SuspendedPageProxy.cpp:
     23        (WebKit::SuspendedPageProxy::SuspendedPageProxy):
     24        * UIProcess/SuspendedPageProxy.h:
     25        * UIProcess/WebProcessPool.cpp:
     26        (WebKit::WebProcessPool::processForNavigationInternal):
     27
    1282018-11-01  Fujii Hironori  <Hironori.Fujii@sony.com>
    229
  • trunk/Source/WebKit/UIProcess/SuspendedPageProxy.cpp

    r237467 r237735  
    7979    , m_process(WTFMove(process))
    8080    , m_mainFrameID(mainFrameID)
    81     , m_origin(SecurityOriginData::fromURL({ { }, item.url() }))
     81    , m_registrableDomain(toRegistrableDomain(URL(URL(), item.url())))
    8282{
    8383    item.setSuspendedPage(*this);
  • trunk/Source/WebKit/UIProcess/SuspendedPageProxy.h

    r237467 r237735  
    4545    WebProcessProxy& process() { return m_process.get(); }
    4646    uint64_t mainFrameID() const { return m_mainFrameID; }
    47     const WebCore::SecurityOriginData& origin() const { return m_origin; }
     47    const String& registrableDomain() const { return m_registrableDomain; }
    4848
    4949    void unsuspend();
     
    6363    Ref<WebProcessProxy> m_process;
    6464    uint64_t m_mainFrameID;
    65     WebCore::SecurityOriginData m_origin;
     65    String m_registrableDomain;
    6666
    6767    bool m_isSuspended { true };
  • trunk/Source/WebKit/UIProcess/WebProcessPool.cpp

    r237700 r237735  
    21862186        reason = "Process swap was requested by the client"_s;
    21872187   
     2188    auto registrableDomain = toRegistrableDomain(targetURL);
    21882189    if (m_configuration->alwaysKeepAndReuseSwappedProcesses()) {
    2189         auto registrableDomain = toRegistrableDomain(targetURL);
    21902190        LOG(ProcessSwapping, "(ProcessSwapping) Considering re-use of a previously cached process for domain %s", registrableDomain.utf8().data());
    21912191
     
    21972197                // In the case where this WebProcess has a SuspendedPageProxy for this WebPage, we can throw it away to support
    21982198                // WebProcess re-use.
    2199                 // In the future it would be great to refactor-out this limitation.
    2200                 page.process().processPool().removeAllSuspendedPageProxiesForPage(page);
     2199                // In the future it would be great to refactor-out this limitation (https://bugs.webkit.org/show_bug.cgi?id=191166).
     2200                m_suspendedPages.removeAllMatching([&](auto& suspendedPage) {
     2201                    return &suspendedPage->page() == &page && &suspendedPage->process() == process;
     2202                });
    22012203
    22022204                return makeRef(*process);
    22032205            }
    22042206        }
     2207    }
     2208
     2209    // Check if we have a suspended page for the given registrable domain and use its process if we do, for performance reasons.
     2210    auto it = m_suspendedPages.findIf([&](auto& suspendedPage) {
     2211        return suspendedPage->registrableDomain() == registrableDomain;
     2212    });
     2213    if (it != m_suspendedPages.end()) {
     2214        Ref<WebProcessProxy> process = (*it)->process();
     2215
     2216        // FIXME: If the SuspendedPage is for this page, then we need to destroy the suspended page as we do not support having
     2217        // multiple WebPages with the same ID in a given WebProcess currently (https://bugs.webkit.org/show_bug.cgi?id=191166).
     2218        if (&(*it)->page() == &page)
     2219            m_suspendedPages.remove(it);
     2220
     2221        if (&process->websiteDataStore() != &page.websiteDataStore())
     2222            process->send(Messages::WebProcess::AddWebsiteDataStore(page.websiteDataStore().parameters()), 0);
     2223
     2224        return process;
    22052225    }
    22062226
  • trunk/Tools/ChangeLog

    r237731 r237735  
     12018-11-02  Chris Dumez  <cdumez@apple.com>
     2
     3        [PSON] Reuse SuspendedPages' process when possible, for performance
     4        https://bugs.webkit.org/show_bug.cgi?id=191166
     5
     6        Reviewed by Geoffrey Garen.
     7
     8        Add API test coverage.
     9
     10        * TestWebKitAPI/Tests/WebKitCocoa/ProcessSwapOnNavigation.mm:
     11
    1122018-11-02  Zalan Bujtas  <zalan@apple.com>
    213
  • trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/ProcessSwapOnNavigation.mm

    r237699 r237735  
    15241524    done = false;
    15251525
    1526     auto pid1 = [webView _webProcessIdentifier];
     1526    auto webkitPID = [webView _webProcessIdentifier];
    15271527
    15281528    request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"pson://www.apple.com/main.html"]];
     
    15321532    done = false;
    15331533
    1534     auto pid2 = [webView _webProcessIdentifier];
     1534    auto applePID = [webView _webProcessIdentifier];
     1535
     1536    // Verify the web pages are in different processes
     1537    EXPECT_NE(webkitPID, applePID);
    15351538
    15361539    request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"pson://www.webkit.org/main.html"]];
     
    15421545    done = false;
    15431546
    1544     auto pid3 = [webView _webProcessIdentifier];
    1545 
    1546     // Verify the web pages are in different processes
    1547     EXPECT_NE(pid1, pid2);
    1548     EXPECT_NE(pid1, pid3);
    1549     EXPECT_NE(pid2, pid3);
     1547    // We should have gone back to the webkit.org process for this load since we reuse SuspendedPages' process when possible.
     1548    EXPECT_EQ(webkitPID, [webView _webProcessIdentifier]);
    15501549
    15511550    // Verify the sessionStorage values were as expected
     
    15531552    EXPECT_TRUE([receivedMessages.get()[0] isEqualToString:@""]);
    15541553    EXPECT_TRUE([receivedMessages.get()[1] isEqualToString:@"I exist!"]);
     1554}
     1555
     1556TEST(ProcessSwap, ReuseSuspendedProcess)
     1557{
     1558    auto processPoolConfiguration = adoptNS([[_WKProcessPoolConfiguration alloc] init]);
     1559    [processPoolConfiguration setProcessSwapsOnNavigation:YES];
     1560    auto processPool = adoptNS([[WKProcessPool alloc] _initWithConfiguration:processPoolConfiguration.get()]);
     1561
     1562    auto webViewConfiguration = adoptNS([[WKWebViewConfiguration alloc] init]);
     1563    [webViewConfiguration setProcessPool:processPool.get()];
     1564    auto handler = adoptNS([[PSONScheme alloc] init]);
     1565    [webViewConfiguration setURLSchemeHandler:handler.get() forURLScheme:@"PSON"];
     1566
     1567    auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:webViewConfiguration.get()]);
     1568    auto delegate = adoptNS([[PSONNavigationDelegate alloc] init]);
     1569    [webView setNavigationDelegate:delegate.get()];
     1570
     1571    NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"pson://www.webkit.org/main1.html"]];
     1572    [webView loadRequest:request];
     1573
     1574    TestWebKitAPI::Util::run(&done);
     1575    done = false;
     1576
     1577    auto webkitPID = [webView _webProcessIdentifier];
     1578
     1579    request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"pson://www.apple.com/main1.html"]];
     1580    [webView loadRequest:request];
     1581
     1582    TestWebKitAPI::Util::run(&done);
     1583    done = false;
     1584
     1585    auto applePID = [webView _webProcessIdentifier];
     1586
     1587    EXPECT_NE(webkitPID, applePID);
     1588
     1589    request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"pson://www.webkit.org/main2.html"]];
     1590    [webView loadRequest:request];
     1591
     1592    TestWebKitAPI::Util::run(&done);
     1593    done = false;
     1594
     1595    // We should have gone back to the webkit.org process for this load since we reuse SuspendedPages' process when possible.
     1596    EXPECT_EQ(webkitPID, [webView _webProcessIdentifier]);
     1597
     1598    request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"pson://www.apple.com/main2.html"]];
     1599    [webView loadRequest:request];
     1600
     1601    TestWebKitAPI::Util::run(&done);
     1602    done = false;
     1603
     1604    // We should have gone back to the apple.com process for this load since we reuse SuspendedPages' process when possible.
     1605    EXPECT_EQ(applePID, [webView _webProcessIdentifier]);
    15551606}
    15561607
Note: See TracChangeset for help on using the changeset viewer.