- Revision
- 137255
- Author
- [email protected]
- Date
- 2012-12-10 23:33:01 -0800 (Mon, 10 Dec 2012)
Log Message
[WK2] Add a user default to limit the number of web processes
https://bugs.webkit.org/show_bug.cgi?id=104606
Reviewed by Sam Weinig.
When the limit is reached, we'll reuse an existing process with fewest pages.
* UIProcess/WebContext.cpp:
(WebKit::WebContext::WebContext): Initialize m_webProcessCountLimit.
(WebKit::WebContext::platformInitialize): Added a hook for reading the preference,
empty implementation on most platforms.
(WebKit::WebContext::createNewWebProcess): Changed to return a raw pointer. The new
process is put into a vector anyway, so there is no ownership transfer.
(WebKit::WebContext::warmInitialProcess): Don't create a new process if that would
exceed the limit.
(WebKit::WebContext::createNewWebProcessRespectingProcessCountLimit): Added a new
function that wither creates a new process, or picks an existing one.
(WebKit::WebContext::createWebPage): Call the above new function instead of
unconditionally creating a process.
* UIProcess/WebContext.h: createNewWebProcess is no private. All clients should
respect the process count limit.
* UIProcess/WebPageProxy.cpp: (WebKit::WebPageProxy::reattachToWebProcess):
Respect the process count limit.
* UIProcess/mac/WebContextMac.mm:
(WebKit::registerUserDefaultsIfNeeded): Register the new default.
(WebKit::WebContext::platformInitialize): Read the default into a WebContext
member variable.
(WebKit::WebContext::platformInitializeWebProcess): Moved registerUserDefaultsIfNeeded()
from here to platformInitialize(), as that's a better place for it. Also added a
FIXME for an unrelated issue.
Modified Paths
Diff
Modified: trunk/Source/WebKit2/ChangeLog (137254 => 137255)
--- trunk/Source/WebKit2/ChangeLog 2012-12-11 07:31:17 UTC (rev 137254)
+++ trunk/Source/WebKit2/ChangeLog 2012-12-11 07:33:01 UTC (rev 137255)
@@ -1,3 +1,39 @@
+2012-12-10 Alexey Proskuryakov <[email protected]>
+
+ [WK2] Add a user default to limit the number of web processes
+ https://bugs.webkit.org/show_bug.cgi?id=104606
+
+ Reviewed by Sam Weinig.
+
+ When the limit is reached, we'll reuse an existing process with fewest pages.
+
+ * UIProcess/WebContext.cpp:
+ (WebKit::WebContext::WebContext): Initialize m_webProcessCountLimit.
+ (WebKit::WebContext::platformInitialize): Added a hook for reading the preference,
+ empty implementation on most platforms.
+ (WebKit::WebContext::createNewWebProcess): Changed to return a raw pointer. The new
+ process is put into a vector anyway, so there is no ownership transfer.
+ (WebKit::WebContext::warmInitialProcess): Don't create a new process if that would
+ exceed the limit.
+ (WebKit::WebContext::createNewWebProcessRespectingProcessCountLimit): Added a new
+ function that wither creates a new process, or picks an existing one.
+ (WebKit::WebContext::createWebPage): Call the above new function instead of
+ unconditionally creating a process.
+
+ * UIProcess/WebContext.h: createNewWebProcess is no private. All clients should
+ respect the process count limit.
+
+ * UIProcess/WebPageProxy.cpp: (WebKit::WebPageProxy::reattachToWebProcess):
+ Respect the process count limit.
+
+ * UIProcess/mac/WebContextMac.mm:
+ (WebKit::registerUserDefaultsIfNeeded): Register the new default.
+ (WebKit::WebContext::platformInitialize): Read the default into a WebContext
+ member variable.
+ (WebKit::WebContext::platformInitializeWebProcess): Moved registerUserDefaultsIfNeeded()
+ from here to platformInitialize(), as that's a better place for it. Also added a
+ FIXME for an unrelated issue.
+
2012-12-10 Jon Lee <[email protected]>
Build fix.
Modified: trunk/Source/WebKit2/UIProcess/WebContext.cpp (137254 => 137255)
--- trunk/Source/WebKit2/UIProcess/WebContext.cpp 2012-12-11 07:31:17 UTC (rev 137254)
+++ trunk/Source/WebKit2/UIProcess/WebContext.cpp 2012-12-11 07:33:01 UTC (rev 137255)
@@ -120,6 +120,7 @@
WebContext::WebContext(ProcessModel processModel, const String& injectedBundlePath)
: m_processModel(processModel)
+ , m_webProcessCountLimit(UINT_MAX)
, m_haveInitialEmptyProcess(false)
, m_defaultPageGroup(WebPageGroup::create())
, m_injectedBundlePath(injectedBundlePath)
@@ -139,6 +140,8 @@
, m_usesNetworkProcess(false)
#endif
{
+ platformInitialize();
+
addMessageReceiver(Messages::WebContext::messageReceiverName(), this);
addMessageReceiver(CoreIPC::MessageKindTraits<WebContextLegacyMessage::Kind>::messageReceiverName(), this);
@@ -184,6 +187,12 @@
#endif
}
+#if !PLATFORM(MAC)
+void WebContext::platformInitialize()
+{
+}
+#endif
+
WebContext::~WebContext()
{
ASSERT(contexts().find(this) != notFound);
@@ -388,7 +397,7 @@
return m_processes[0].get();
}
-PassRefPtr<WebProcessProxy> WebContext::createNewWebProcess()
+WebProcessProxy* WebContext::createNewWebProcess()
{
#if ENABLE(NETWORK_PROCESS)
if (m_usesNetworkProcess)
@@ -480,8 +489,7 @@
} else
ASSERT(m_messagesToInjectedBundlePostedToEmptyContext.isEmpty());
-
- return process.release();
+ return process.get();
}
void WebContext::warmInitialProcess()
@@ -491,6 +499,9 @@
return;
}
+ if (m_processes.size() >= m_webProcessCountLimit)
+ return;
+
createNewWebProcess();
m_haveInitialEmptyProcess = true;
}
@@ -615,6 +626,23 @@
m_processes.remove(m_processes.find(process));
}
+WebProcessProxy* WebContext::createNewWebProcessRespectingProcessCountLimit()
+{
+ if (m_processes.size() < m_webProcessCountLimit)
+ return createNewWebProcess();
+
+ // Choose a process with fewest pages, to achieve flat distribution.
+ WebProcessProxy* result = 0;
+ unsigned fewestPagesSeen = UINT_MAX;
+ for (unsigned i = 0; i < m_processes.size(); ++i) {
+ if (fewestPagesSeen > m_processes[i]->pages().size()) {
+ result = m_processes[i].get();
+ fewestPagesSeen = m_processes[i]->pages().size();
+ }
+ }
+ return result;
+}
+
PassRefPtr<WebPageProxy> WebContext::createWebPage(PageClient* pageClient, WebPageGroup* pageGroup, WebPageProxy* relatedPage)
{
RefPtr<WebProcessProxy> process;
@@ -627,10 +655,8 @@
} else if (relatedPage) {
// Sharing processes, e.g. when creating the page via window.open().
process = relatedPage->process();
- } else {
- // FIXME (Multi-WebProcess): <rdar://problem/12239661> Consider limiting the number of web processes in per-tab process model.
- process = createNewWebProcess();
- }
+ } else
+ process = createNewWebProcessRespectingProcessCountLimit();
}
if (!pageGroup)
Modified: trunk/Source/WebKit2/UIProcess/WebContext.h (137254 => 137255)
--- trunk/Source/WebKit2/UIProcess/WebContext.h 2012-12-11 07:31:17 UTC (rev 137254)
+++ trunk/Source/WebKit2/UIProcess/WebContext.h 2012-12-11 07:33:01 UTC (rev 137255)
@@ -220,7 +220,7 @@
void setCookieStorageDirectory(const String& dir) { m_overrideCookieStorageDirectory = dir; }
WebProcessProxy* ensureSharedWebProcess();
- PassRefPtr<WebProcessProxy> createNewWebProcess();
+ WebProcessProxy* createNewWebProcessRespectingProcessCountLimit(); // Will return an existing one if limit is met.
void warmInitialProcess();
bool shouldTerminate(WebProcessProxy*);
@@ -256,12 +256,15 @@
private:
WebContext(ProcessModel, const String& injectedBundlePath);
+ void platformInitialize();
virtual Type type() const { return APIType; }
void platformInitializeWebProcess(WebProcessCreationParameters&);
void platformInvalidateContext();
+ WebProcessProxy* createNewWebProcess();
+
#if PLATFORM(MAC)
void getPasteboardTypes(const String& pasteboardName, Vector<String>& pasteboardTypes);
void getPasteboardPathnamesForType(const String& pasteboardName, const String& pasteboardType, Vector<String>& pathnames);
@@ -318,6 +321,7 @@
void addPlugInAutoStartOriginHash(const String& pageOrigin, unsigned plugInOriginHash);
ProcessModel m_processModel;
+ unsigned m_webProcessCountLimit; // The limit has no effect when process model is ProcessModelSharedSecondaryProcess.
Vector<RefPtr<WebProcessProxy> > m_processes;
bool m_haveInitialEmptyProcess;
Modified: trunk/Source/WebKit2/UIProcess/WebPageProxy.cpp (137254 => 137255)
--- trunk/Source/WebKit2/UIProcess/WebPageProxy.cpp 2012-12-11 07:31:17 UTC (rev 137254)
+++ trunk/Source/WebKit2/UIProcess/WebPageProxy.cpp 2012-12-11 07:33:01 UTC (rev 137255)
@@ -385,7 +385,7 @@
if (m_process->context()->processModel() == ProcessModelSharedSecondaryProcess)
m_process = m_process->context()->ensureSharedWebProcess();
else
- m_process = m_process->context()->createNewWebProcess();
+ m_process = m_process->context()->createNewWebProcessRespectingProcessCountLimit();
m_process->addExistingWebPage(this, m_pageID);
initializeWebPage();
Modified: trunk/Source/WebKit2/UIProcess/mac/WebContextMac.mm (137254 => 137255)
--- trunk/Source/WebKit2/UIProcess/mac/WebContextMac.mm 2012-12-11 07:31:17 UTC (rev 137254)
+++ trunk/Source/WebKit2/UIProcess/mac/WebContextMac.mm 2012-12-11 07:33:01 UTC (rev 137255)
@@ -47,6 +47,7 @@
NSString *WebKitLocalCacheDefaultsKey = @"WebKitLocalCache";
NSString *WebStorageDirectoryDefaultsKey = @"WebKitLocalStorageDatabasePathPreferenceKey";
NSString *WebKitKerningAndLigaturesEnabledByDefaultDefaultsKey = @"WebKitKerningAndLigaturesEnabledByDefault";
+NSString *WebKitWebProcessCountLimitDefaultsKey = @"WebKitWebProcessCountLimit";
static NSString *WebKitApplicationDidChangeAccessibilityEnhancedUserInterfaceNotification = @"NSApplicationDidChangeAccessibilityEnhancedUserInterfaceNotification";
@@ -60,6 +61,32 @@
bool WebContext::s_applicationIsOccluded = false;
+static void registerUserDefaultsIfNeeded()
+{
+ static bool didRegister;
+ if (didRegister)
+ return;
+
+ didRegister = true;
+ NSMutableDictionary *registrationDictionary = [NSMutableDictionary dictionary];
+
+ [registrationDictionary setObject:[NSNumber numberWithInteger:INT_MAX] forKey:WebKitWebProcessCountLimitDefaultsKey];
+#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1090
+ [registrationDictionary setObject:[NSNumber numberWithBool:YES] forKey:WebKitKerningAndLigaturesEnabledByDefaultDefaultsKey];
+#endif
+
+ [[NSUserDefaults standardUserDefaults] registerDefaults:registrationDictionary];
+}
+
+void WebContext::platformInitialize()
+{
+ registerUserDefaultsIfNeeded();
+
+ m_webProcessCountLimit = [[NSUserDefaults standardUserDefaults] integerForKey:WebKitWebProcessCountLimitDefaultsKey];
+ if (m_webProcessCountLimit <= 0)
+ m_webProcessCountLimit = 1;
+}
+
String WebContext::applicationCacheDirectory()
{
NSString *appName = [[NSBundle mainBundle] bundleIdentifier];
@@ -82,18 +109,6 @@
return [cacheDir stringByAppendingPathComponent:appName];
}
-static void registerUserDefaultsIfNeeded()
-{
- static bool didRegister;
- if (didRegister)
- return;
-
- didRegister = true;
-#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1090
- [[NSUserDefaults standardUserDefaults] registerDefaults:[NSDictionary dictionaryWithObject:[NSNumber numberWithBool:YES] forKey:WebKitKerningAndLigaturesEnabledByDefaultDefaultsKey]];
-#endif
-}
-
void WebContext::platformInitializeWebProcess(WebProcessCreationParameters& parameters)
{
parameters.presenterApplicationPid = getpid();
@@ -102,7 +117,6 @@
parameters.nsURLCacheMemoryCapacity = [urlCache memoryCapacity];
parameters.nsURLCacheDiskCapacity = [urlCache diskCapacity];
- registerUserDefaultsIfNeeded();
#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1090
parameters.shouldForceScreenFontSubstitution = [[NSUserDefaults standardUserDefaults] boolForKey:@"NSFontDefaultScreenFontSubstitutionEnabled"];
#endif
@@ -123,7 +137,9 @@
NSArray *schemes = [[WKBrowsingContextController customSchemes] allObjects];
for (size_t i = 0; i < [schemes count]; ++i)
parameters.urlSchemesRegisteredForCustomProtocols.append([schemes objectAtIndex:i]);
-
+
+ // FIXME(Multi-WebProcess): We register observers for every process that is created, which makes no sense.
+
m_customSchemeRegisteredObserver = [[NSNotificationCenter defaultCenter] addObserverForName:WebKit::SchemeForCustomProtocolRegisteredNotificationName object:nil queue:[NSOperationQueue currentQueue] usingBlock:^(NSNotification *notification) {
NSString *scheme = [notification object];
ASSERT([scheme isKindOfClass:[NSString class]]);