Bug 180819 - Avoid waking plugin process up unnecessarily
Summary: Avoid waking plugin process up unnecessarily
Status: RESOLVED FIXED
Alias: None
Product: WebKit
Classification: Unclassified
Component: WebKit Misc. (show other bugs)
Version: WebKit Nightly Build
Hardware: Unspecified Unspecified
: P2 Normal
Assignee: Brent Fulgham
URL:
Keywords: InRadar
Depends on:
Blocks:
 
Reported: 2017-12-14 10:25 PST by Brent Fulgham
Modified: 2017-12-15 13:27 PST (History)
5 users (show)

See Also:


Attachments
Patch (14.29 KB, patch)
2017-12-14 10:59 PST, Brent Fulgham
no flags Details | Formatted Diff | Diff
Patch (14.32 KB, patch)
2017-12-14 12:08 PST, Brent Fulgham
no flags Details | Formatted Diff | Diff
Patch (14.29 KB, patch)
2017-12-15 09:16 PST, Brent Fulgham
ggaren: review+
Details | Formatted Diff | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Brent Fulgham 2017-12-14 10:25:21 PST
WebKit purges data from origins marked as prevalent on an hourly interval. This includes waking up plugins and removing relevant data stored in those plugins. This causes multiple plugin processes to be spawned, even though the user is not interacting with any plugins.

Instead, we should delay removing data from plugins until they are loaded due to the user interacting with a website using a plugin.

Make the following changes:

1. When looking for plugin data related to prevalent sites, only examine plugin data if the relevant plugin is already running.
2. When the state of the active plugins changes, trigger a data removal check.
Comment 1 Brent Fulgham 2017-12-14 10:32:57 PST
<rdar://problem/36051548>
Comment 2 Brent Fulgham 2017-12-14 10:59:58 PST
Created attachment 329367 [details]
Patch
Comment 3 Build Bot 2017-12-14 11:02:29 PST
Attachment 329367 [details] did not pass style-queue:


ERROR: Source/WebKit/UIProcess/Plugins/PluginProcessManager.cpp:99:  Extra space before ( in function call  [whitespace/parens] [4]
ERROR: Source/WebKit/UIProcess/Plugins/PluginProcessManager.h:63:  Extra space before ( in function call  [whitespace/parens] [4]
Total errors found: 2 in 8 files


If any of these errors are false positives, please file a bug against check-webkit-style.
Comment 4 Brent Fulgham 2017-12-14 12:08:18 PST
Created attachment 329377 [details]
Patch
Comment 5 Build Bot 2017-12-14 12:10:49 PST
Attachment 329377 [details] did not pass style-queue:


ERROR: Source/WebKit/UIProcess/Plugins/PluginProcessManager.cpp:99:  Extra space before ( in function call  [whitespace/parens] [4]
ERROR: Source/WebKit/UIProcess/Plugins/PluginProcessManager.h:63:  Extra space before ( in function call  [whitespace/parens] [4]
Total errors found: 2 in 8 files


If any of these errors are false positives, please file a bug against check-webkit-style.
Comment 6 Brent Fulgham 2017-12-14 17:42:50 PST
I think this approach would allow us to do the same for the Database Process.
Comment 7 Geoffrey Garen 2017-12-14 18:12:34 PST
Comment on attachment 329377 [details]
Patch

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

r- because I think the count thing is wrong.

The rest of my comments are aesthetic preferences, but they probably don't make the code wrong.

> Source/WebKit/Shared/WebsiteData/WebsiteDataFetchOption.h:32
> +    DoNotCreateProcesses = 1 << 1,

I think this would make more sense if it were an affirmative value, "LaunchPluginProcesses". Launching plugin processes and computing sizes are both optional additions to the standard fetch operation, with additional cost, which we would like to avoid if we can. Generally speaking, flags make more sense when they indicate the presence of something. Otherwise, you end up with double negatives like "if (!(x & DoNotCreateProcesses))", which reads "if I do not have the do not create processes option set", which hurts my brain.

> Source/WebKit/UIProcess/WebProcessProxy.cpp:248
> +    OptionSet<WebKit::WebsiteDataFetchOption> fetchOptions = WebKit::WebsiteDataFetchOption::DoNotCreateProcesses;

I'm curious -- does anybody ever specify DO create processes?

> Source/WebKit/UIProcess/WebResourceLoadStatisticsStore.cpp:638
> +    auto activePluginCount = WebKit::PluginProcessManager::singleton().pluginProcesses().size();
> +    if (activePluginCount != m_activePluginCount)
> +        return true;

What happens if a new plugin launches and an old plugin exits? It seems like you would decide that the count is the same, and do nothing. I don't think that's right. Or do plugins never exit, and does the active count only go up? If so, you should assert that.

> Source/WebKit/UIProcess/Plugins/PluginProcessManager.cpp:122
> +PluginProcessProxy* PluginProcessManager::getOrCreatePluginProcess(uint64_t pluginProcessToken, ProcessAccessType processesAccessType)

I think it would be clearer if you broke this into two functions: get, and getOrCreate, with getOrCreate calling get. It's too weird for getOrCreate to take a parameter that specifies "just kidding, don't create".

The caller can call get or getOrCreate depending on its needs.

> Source/WebKit/UIProcess/Plugins/PluginProcessManager.h:63
> +    enum class ProcessAccessType { OnlyIfLaunched, Launch };
> +    void fetchWebsiteData(const PluginModuleInfo&, ProcessAccessType createProcessesBehavior, WTF::Function<void (Vector<String>)>&& completionHandler);

I think you can use the WebsiteDataFetchOption enum here. This function is about fetching website data.
Comment 8 Brent Fulgham 2017-12-15 08:56:05 PST
Comment on attachment 329377 [details]
Patch

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

>> Source/WebKit/Shared/WebsiteData/WebsiteDataFetchOption.h:32
>> +    DoNotCreateProcesses = 1 << 1,
> 
> I think this would make more sense if it were an affirmative value, "LaunchPluginProcesses". Launching plugin processes and computing sizes are both optional additions to the standard fetch operation, with additional cost, which we would like to avoid if we can. Generally speaking, flags make more sense when they indicate the presence of something. Otherwise, you end up with double negatives like "if (!(x & DoNotCreateProcesses))", which reads "if I do not have the do not create processes option set", which hurts my brain.

I can see your point, but this new option is an edge case. In all places where WebsiteDataFetch operations are happening, we expect processes to be launched so that their plugin data (or database data) can be inspected or deleted. The case I'm addressing in this patch is a high-frequency probe of website data, where we do not want to spawn new processes if they don't already exist. Using a positive flag name here would make users of the API have to set a flag for the 'normal' case, and not setting the flag would give you the 'unusual' case.

I think making the default behavior the "unusual" use case would lead to mistakes by people unfamiliar with the code.

>> Source/WebKit/UIProcess/WebProcessProxy.cpp:248
>> +    OptionSet<WebKit::WebsiteDataFetchOption> fetchOptions = WebKit::WebsiteDataFetchOption::DoNotCreateProcesses;
> 
> I'm curious -- does anybody ever specify DO create processes?

All uses of the fetch and delete API to date expect processes to be automatically spawned to do the work. So the ResourceLoadStatistics case is an unusual edge case, where we want to opportunistically inspect running processes, but don't want to pay the cost to launch them.

>> Source/WebKit/UIProcess/WebResourceLoadStatisticsStore.cpp:638
>> +        return true;
> 
> What happens if a new plugin launches and an old plugin exits? It seems like you would decide that the count is the same, and do nothing. I don't think that's right. Or do plugins never exit, and does the active count only go up? If so, you should assert that.

Yeah -- I thought about this, too, but I was worried that would make this overly complicated. However, it looks like the plugin process proxies all carry around a custom token we can use to distinguish them. I'll use that to decide whether the trigger the data fetch.n

>> Source/WebKit/UIProcess/Plugins/PluginProcessManager.cpp:122
>> +PluginProcessProxy* PluginProcessManager::getOrCreatePluginProcess(uint64_t pluginProcessToken, ProcessAccessType processesAccessType)
> 
> I think it would be clearer if you broke this into two functions: get, and getOrCreate, with getOrCreate calling get. It's too weird for getOrCreate to take a parameter that specifies "just kidding, don't create".
> 
> The caller can call get or getOrCreate depending on its needs.

Lol. Sounds good! I'll change it.

>> Source/WebKit/UIProcess/Plugins/PluginProcessManager.h:63
>> +    void fetchWebsiteData(const PluginModuleInfo&, ProcessAccessType createProcessesBehavior, WTF::Function<void (Vector<String>)>&& completionHandler);
> 
> I think you can use the WebsiteDataFetchOption enum here. This function is about fetching website data.

Sounds good.
Comment 9 Brent Fulgham 2017-12-15 09:16:38 PST
Created attachment 329490 [details]
Patch
Comment 10 Build Bot 2017-12-15 09:18:04 PST
Attachment 329490 [details] did not pass style-queue:


ERROR: Source/WebKit/UIProcess/Plugins/PluginProcessManager.cpp:100:  Extra space before ( in function call  [whitespace/parens] [4]
ERROR: Source/WebKit/UIProcess/Plugins/PluginProcessManager.h:63:  Extra space before ( in function call  [whitespace/parens] [4]
Total errors found: 2 in 8 files


If any of these errors are false positives, please file a bug against check-webkit-style.
Comment 11 Geoffrey Garen 2017-12-15 12:53:00 PST
Comment on attachment 329490 [details]
Patch

r=me
Comment 12 Brent Fulgham 2017-12-15 13:27:26 PST
Committed r225984: <https://trac.webkit.org/changeset/225984>