Skip to content

Commit

Permalink
[WK2] Add a user default to limit the number of web processes
Browse files Browse the repository at this point in the history
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.


git-svn-id: http://svn.webkit.org/repository/webkit/trunk@137255 268f45cc-cd09-0410-ab3c-d52691b4dbfc
  • Loading branch information
aproskuryakov committed Dec 11, 2012
1 parent 3475f1c commit eca3f81
Show file tree
Hide file tree
Showing 5 changed files with 105 additions and 23 deletions.
36 changes: 36 additions & 0 deletions Source/WebKit2/ChangeLog
@@ -1,3 +1,39 @@
2012-12-10 Alexey Proskuryakov <ap@apple.com>

[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 <jonlee@apple.com>

Build fix.
Expand Down
40 changes: 33 additions & 7 deletions Source/WebKit2/UIProcess/WebContext.cpp
Expand Up @@ -120,6 +120,7 @@ const Vector<WebContext*>& WebContext::allContexts()

WebContext::WebContext(ProcessModel processModel, const String& injectedBundlePath)
: m_processModel(processModel)
, m_webProcessCountLimit(UINT_MAX)
, m_haveInitialEmptyProcess(false)
, m_defaultPageGroup(WebPageGroup::create())
, m_injectedBundlePath(injectedBundlePath)
Expand All @@ -139,6 +140,8 @@ WebContext::WebContext(ProcessModel processModel, const String& injectedBundlePa
, m_usesNetworkProcess(false)
#endif
{
platformInitialize();

addMessageReceiver(Messages::WebContext::messageReceiverName(), this);
addMessageReceiver(CoreIPC::MessageKindTraits<WebContextLegacyMessage::Kind>::messageReceiverName(), this);

Expand Down Expand Up @@ -184,6 +187,12 @@ WebContext::WebContext(ProcessModel processModel, const String& injectedBundlePa
#endif
}

#if !PLATFORM(MAC)
void WebContext::platformInitialize()
{
}
#endif

WebContext::~WebContext()
{
ASSERT(contexts().find(this) != notFound);
Expand Down Expand Up @@ -388,7 +397,7 @@ WebProcessProxy* WebContext::ensureSharedWebProcess()
return m_processes[0].get();
}

PassRefPtr<WebProcessProxy> WebContext::createNewWebProcess()
WebProcessProxy* WebContext::createNewWebProcess()
{
#if ENABLE(NETWORK_PROCESS)
if (m_usesNetworkProcess)
Expand Down Expand Up @@ -480,8 +489,7 @@ PassRefPtr<WebProcessProxy> WebContext::createNewWebProcess()
} else
ASSERT(m_messagesToInjectedBundlePostedToEmptyContext.isEmpty());


return process.release();
return process.get();
}

void WebContext::warmInitialProcess()
Expand All @@ -491,6 +499,9 @@ void WebContext::warmInitialProcess()
return;
}

if (m_processes.size() >= m_webProcessCountLimit)
return;

createNewWebProcess();
m_haveInitialEmptyProcess = true;
}
Expand Down Expand Up @@ -615,6 +626,23 @@ void WebContext::disconnectProcess(WebProcessProxy* process)
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;
Expand All @@ -627,10 +655,8 @@ PassRefPtr<WebPageProxy> WebContext::createWebPage(PageClient* pageClient, WebPa
} 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)
Expand Down
6 changes: 5 additions & 1 deletion Source/WebKit2/UIProcess/WebContext.h
Expand Up @@ -220,7 +220,7 @@ class WebContext : public APIObject, private CoreIPC::MessageReceiver {
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*);
Expand Down Expand Up @@ -256,12 +256,15 @@ class WebContext : public APIObject, private CoreIPC::MessageReceiver {

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);
Expand Down Expand Up @@ -318,6 +321,7 @@ class WebContext : public APIObject, private CoreIPC::MessageReceiver {
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;
Expand Down
2 changes: 1 addition & 1 deletion Source/WebKit2/UIProcess/WebPageProxy.cpp
Expand Up @@ -385,7 +385,7 @@ void WebPageProxy::reattachToWebProcess()
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();
Expand Down
44 changes: 30 additions & 14 deletions Source/WebKit2/UIProcess/mac/WebContextMac.mm
Expand Up @@ -47,6 +47,7 @@
NSString *WebKitLocalCacheDefaultsKey = @"WebKitLocalCache";
NSString *WebStorageDirectoryDefaultsKey = @"WebKitLocalStorageDatabasePathPreferenceKey";
NSString *WebKitKerningAndLigaturesEnabledByDefaultDefaultsKey = @"WebKitKerningAndLigaturesEnabledByDefault";
NSString *WebKitWebProcessCountLimitDefaultsKey = @"WebKitWebProcessCountLimit";

static NSString *WebKitApplicationDidChangeAccessibilityEnhancedUserInterfaceNotification = @"NSApplicationDidChangeAccessibilityEnhancedUserInterfaceNotification";

Expand All @@ -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];
Expand All @@ -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();
Expand All @@ -102,7 +117,6 @@ static void registerUserDefaultsIfNeeded()
parameters.nsURLCacheMemoryCapacity = [urlCache memoryCapacity];
parameters.nsURLCacheDiskCapacity = [urlCache diskCapacity];

registerUserDefaultsIfNeeded();
#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1090
parameters.shouldForceScreenFontSubstitution = [[NSUserDefaults standardUserDefaults] boolForKey:@"NSFontDefaultScreenFontSubstitutionEnabled"];
#endif
Expand All @@ -123,7 +137,9 @@ static void registerUserDefaultsIfNeeded()
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]]);
Expand Down

0 comments on commit eca3f81

Please sign in to comment.