Changeset 83324 in webkit


Ignore:
Timestamp:
Apr 8, 2011 12:33:04 PM (13 years ago)
Author:
mjs@apple.com
Message:

2011-04-08 Maciej Stachowiak <mjs@apple.com>

Reviewed by Darin Adler.

-[WebView setPreferences:] can take a lot of time if loading lots of webviews at once
https://bugs.webkit.org/show_bug.cgi?id=58128
<rdar://problem/9244553>


The root of the problem here was an O(N2) issue - each WebView,
upon having its preferences initialized, would broadcast a
notification that was listened to by all other WebViews sharing
its preferences.


To maintain the API contract, I split the notification into two,
one that is for public API consumption, and the other which is for
internal use only. Changes that don't need to be picked up by
other WebViews broadcast the public notification only. And we
avoid WebView broadcasting a notification just to get itself to
update.

  • Misc/WebIconDatabase.mm: (-[WebIconDatabase _startUpIconDatabase]): (-[WebIconDatabase _shutDownIconDatabase]):
  • Plugins/WebBaseNetscapePluginView.mm: (-[WebBaseNetscapePluginView viewWillMoveToWindow:]): (-[WebBaseNetscapePluginView viewWillMoveToSuperview:]): (-[WebBaseNetscapePluginView viewDidMoveToWindow]): (-[WebBaseNetscapePluginView viewWillMoveToHostWindow:]):
  • WebView/WebPreferences.mm: (-[WebPreferences initWithIdentifier:]): (-[WebPreferences _setStringValue:forKey:]): (-[WebPreferences _setIntegerValue:forKey:]): (-[WebPreferences _setFloatValue:forKey:]): (-[WebPreferences _setBoolValue:forKey:]): (-[WebPreferences _setLongLongValue:forKey:]): (-[WebPreferences _setUnsignedLongLongValue:forKey:]): (-[WebPreferences _postPreferencesChangedNotification]): (-[WebPreferences _postPreferencesChangedAPINotification]):
  • WebView/WebPreferencesPrivate.h:
  • WebView/WebView.mm: (-[WebView _commonInitializationWithFrameName:groupName:usesDocumentViews:]): (-[WebView _preferencesChangedNotification:]): (-[WebView _preferencesChanged:]): (-[WebView setUsesPageCache:]): (+[WebView initialize]): (-[WebView setPreferences:]): (-[WebView _keyboardUIMode]):
  • WebView/WebViewInternal.h:
Location:
trunk/Source/WebKit/mac
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebKit/mac/ChangeLog

    r83223 r83324  
     12011-04-08  Maciej Stachowiak  <mjs@apple.com>
     2
     3        Reviewed by Darin Adler.
     4
     5        -[WebView setPreferences:] can take a lot of time if loading lots of webviews at once
     6        https://bugs.webkit.org/show_bug.cgi?id=58128
     7        <rdar://problem/9244553>
     8       
     9        The root of the problem here was an O(N^2) issue - each WebView,
     10        upon having its preferences initialized, would broadcast a
     11        notification that was listened to by all other WebViews sharing
     12        its preferences.
     13       
     14        To maintain the API contract, I split the notification into two,
     15        one that is for public API consumption, and the other which is for
     16        internal use only. Changes that don't need to be picked up by
     17        other WebViews broadcast the public notification only. And we
     18        avoid WebView broadcasting a notification just to get itself to
     19        update.
     20
     21        * Misc/WebIconDatabase.mm:
     22        (-[WebIconDatabase _startUpIconDatabase]):
     23        (-[WebIconDatabase _shutDownIconDatabase]):
     24        * Plugins/WebBaseNetscapePluginView.mm:
     25        (-[WebBaseNetscapePluginView viewWillMoveToWindow:]):
     26        (-[WebBaseNetscapePluginView viewWillMoveToSuperview:]):
     27        (-[WebBaseNetscapePluginView viewDidMoveToWindow]):
     28        (-[WebBaseNetscapePluginView viewWillMoveToHostWindow:]):
     29        * WebView/WebPreferences.mm:
     30        (-[WebPreferences initWithIdentifier:]):
     31        (-[WebPreferences _setStringValue:forKey:]):
     32        (-[WebPreferences _setIntegerValue:forKey:]):
     33        (-[WebPreferences _setFloatValue:forKey:]):
     34        (-[WebPreferences _setBoolValue:forKey:]):
     35        (-[WebPreferences _setLongLongValue:forKey:]):
     36        (-[WebPreferences _setUnsignedLongLongValue:forKey:]):
     37        (-[WebPreferences _postPreferencesChangedNotification]):
     38        (-[WebPreferences _postPreferencesChangedAPINotification]):
     39        * WebView/WebPreferencesPrivate.h:
     40        * WebView/WebView.mm:
     41        (-[WebView _commonInitializationWithFrameName:groupName:usesDocumentViews:]):
     42        (-[WebView _preferencesChangedNotification:]):
     43        (-[WebView _preferencesChanged:]):
     44        (-[WebView setUsesPageCache:]):
     45        (+[WebView initialize]):
     46        (-[WebView setPreferences:]):
     47        (-[WebView _keyboardUIMode]):
     48        * WebView/WebViewInternal.h:
     49
    1502011-04-07  Andrew Scherkus  <scherkus@chromium.org>
    251
  • trunk/Source/WebKit/mac/Misc/WebIconDatabase.mm

    r81824 r83324  
    3636#import "WebNSNotificationCenterExtras.h"
    3737#import "WebNSURLExtras.h"
    38 #import "WebPreferences.h"
     38#import "WebPreferencesPrivate.h"
    3939#import "WebTypesInternal.h"
    4040#import <WebCore/IconDatabase.h>
     
    314314    [[NSNotificationCenter defaultCenter] addObserver:self
    315315                                             selector:@selector(_resetCachedWebPreferences:)
    316                                                  name:WebPreferencesChangedNotification
     316                                                 name:WebPreferencesChangedInternalNotification
    317317                                               object:nil];
    318318}
     
    325325                                                  object:NSApp];
    326326    [[NSNotificationCenter defaultCenter] removeObserver:self
    327                                                     name:WebPreferencesChangedNotification
     327                                                    name:WebPreferencesChangedInternalNotification
    328328                                                  object:nil];
    329329}
  • trunk/Source/WebKit/mac/Plugins/WebBaseNetscapePluginView.mm

    r82723 r83324  
    620620            [self stop];
    621621           
    622             // Stop observing WebPreferencesChangedNotification -- we only need to observe this when installed in the view hierarchy.
     622            // Stop observing WebPreferencesChangedInternalNotification -- we only need to observe this when installed in the view hierarchy.
    623623            // When not in the view hierarchy, -viewWillMoveToWindow: and -viewDidMoveToWindow will start/stop the plugin as needed.
    624             [[NSNotificationCenter defaultCenter] removeObserver:self name:WebPreferencesChangedNotification object:nil];
     624            [[NSNotificationCenter defaultCenter] removeObserver:self name:WebPreferencesChangedInternalNotification object:nil];
    625625        }
    626626    }
     
    635635        [self stop];
    636636       
    637         // Stop observing WebPreferencesChangedNotification -- we only need to observe this when installed in the view hierarchy.
     637        // Stop observing WebPreferencesChangedInternalNotification -- we only need to observe this when installed in the view hierarchy.
    638638        // When not in the view hierarchy, -viewWillMoveToWindow: and -viewDidMoveToWindow will start/stop the plugin as needed.
    639         [[NSNotificationCenter defaultCenter] removeObserver:self name:WebPreferencesChangedNotification object:nil];
     639        [[NSNotificationCenter defaultCenter] removeObserver:self name:WebPreferencesChangedInternalNotification object:nil];
    640640    }
    641641}
     
    646646   
    647647    if ([self window]) {
    648         // While in the view hierarchy, observe WebPreferencesChangedNotification so that we can start/stop depending
     648        // While in the view hierarchy, observe WebPreferencesChangedInternalNotification so that we can start/stop depending
    649649        // on whether plugins are enabled.
    650650        [[NSNotificationCenter defaultCenter] addObserver:self
    651651                                                 selector:@selector(preferencesHaveChanged:)
    652                                                      name:WebPreferencesChangedNotification
     652                                                     name:WebPreferencesChangedInternalNotification
    653653                                                   object:nil];
    654654
     
    678678        [self stop];
    679679       
    680         // Remove WebPreferencesChangedNotification observer -- we will observe once again when we move back into the window
    681         [[NSNotificationCenter defaultCenter] removeObserver:self name:WebPreferencesChangedNotification object:nil];
     680        // Remove WebPreferencesChangedInternalNotification observer -- we will observe once again when we move back into the window
     681        [[NSNotificationCenter defaultCenter] removeObserver:self name:WebPreferencesChangedInternalNotification object:nil];
    682682    }
    683683}
  • trunk/Source/WebKit/mac/WebView/WebPreferences.mm

    r82052 r83324  
    4343NSString *WebPreferencesChangedNotification = @"WebPreferencesChangedNotification";
    4444NSString *WebPreferencesRemovedNotification = @"WebPreferencesRemovedNotification";
     45NSString *WebPreferencesChangedInternalNotification = @"WebPreferencesChangedInternalNotification";
    4546
    4647#define KEY(x) (_private->identifier ? [_private->identifier stringByAppendingString:(x)] : (x))
     
    233234    [[self class] _setInstance:self forIdentifier:_private->identifier];
    234235
    235     [self _postPreferencesChangesNotification];
     236    [self _postPreferencesChangedNotification];
    236237
    237238    return self;
     
    437438    if (_private->autosaves)
    438439        [[NSUserDefaults standardUserDefaults] setObject:value forKey:_key];
    439     [self _postPreferencesChangesNotification];
     440    [self _postPreferencesChangedNotification];
    440441}
    441442
     
    454455    if (_private->autosaves)
    455456        [[NSUserDefaults standardUserDefaults] setInteger:value forKey:_key];
    456     [self _postPreferencesChangesNotification];
     457    [self _postPreferencesChangedNotification];
    457458}
    458459
     
    471472    if (_private->autosaves)
    472473        [[NSUserDefaults standardUserDefaults] setFloat:value forKey:_key];
    473     [self _postPreferencesChangesNotification];
     474    [self _postPreferencesChangedNotification];
    474475}
    475476
     
    487488    if (_private->autosaves)
    488489        [[NSUserDefaults standardUserDefaults] setBool:value forKey:_key];
    489     [self _postPreferencesChangesNotification];
     490    [self _postPreferencesChangedNotification];
    490491}
    491492
     
    504505    if (_private->autosaves)
    505506        [[NSUserDefaults standardUserDefaults] setObject:[NSNumber numberWithLongLong:value] forKey:_key];
    506     [self _postPreferencesChangesNotification];
     507    [self _postPreferencesChangedNotification];
    507508}
    508509
     
    521522    if (_private->autosaves)
    522523        [[NSUserDefaults standardUserDefaults] setObject:[NSNumber numberWithUnsignedLongLong:value] forKey:_key];
    523     [self _postPreferencesChangesNotification];
     524    [self _postPreferencesChangedNotification];
    524525}
    525526
     
    11741175}
    11751176
    1176 - (void)_postPreferencesChangesNotification
     1177- (void)_postPreferencesChangedNotification
    11771178{
    11781179    if (!pthread_main_np()) {
     
    11811182    }
    11821183
    1183     [[NSNotificationCenter defaultCenter]
    1184         postNotificationName:WebPreferencesChangedNotification object:self
    1185                     userInfo:nil];
     1184    [[NSNotificationCenter defaultCenter] postNotificationName:WebPreferencesChangedInternalNotification object:self userInfo:nil];
     1185    [[NSNotificationCenter defaultCenter] postNotificationName:WebPreferencesChangedNotification object:self userInfo:nil];
     1186}
     1187
     1188- (void)_postPreferencesChangedAPINotification
     1189{
     1190    if (!pthread_main_np()) {
     1191        [self performSelectorOnMainThread:_cmd withObject:nil waitUntilDone:NO];
     1192        return;
     1193    }
     1194
     1195    [[NSNotificationCenter defaultCenter] postNotificationName:WebPreferencesChangedNotification object:self userInfo:nil];
    11861196}
    11871197
  • trunk/Source/WebKit/mac/WebView/WebPreferencesPrivate.h

    r81635 r83324  
    5252extern NSString *WebPreferencesChangedNotification;
    5353extern NSString *WebPreferencesRemovedNotification;
     54extern NSString *WebPreferencesChangedInternalNotification;
    5455
    5556@interface WebPreferences (WebPrivate)
     
    211212
    212213// Other private methods
    213 - (void)_postPreferencesChangesNotification;
     214- (void)_postPreferencesChangedNotification;
     215- (void)_postPreferencesChangedAPINotification;
    214216+ (WebPreferences *)_getInstanceForIdentifier:(NSString *)identifier;
    215217+ (void)_setInstance:(WebPreferences *)instance forIdentifier:(NSString *)identifier;
  • trunk/Source/WebKit/mac/WebView/WebView.mm

    r83201 r83324  
    778778    WebPreferences *prefs = [self preferences];
    779779    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_preferencesChangedNotification:)
    780                                                  name:WebPreferencesChangedNotification object:prefs];
    781 
    782     // Post a notification so the WebCore settings update.
    783     [[self preferences] _postPreferencesChangesNotification];
     780                                                 name:WebPreferencesChangedInternalNotification object:prefs];
     781
     782    [self _preferencesChanged:[self preferences]];
     783    [[self preferences] _postPreferencesChangedAPINotification];
    784784
    785785    if (!WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITH_LOCAL_RESOURCE_SECURITY_RESTRICTION)) {
     
    14421442{
    14431443    WebPreferences *preferences = (WebPreferences *)[notification object];
     1444    [self _preferencesChanged:preferences];
     1445}
     1446
     1447- (void)_preferencesChanged:(WebPreferences *)preferences
     1448{   
    14441449    ASSERT(preferences == [self preferences]);
    1445    
    14461450    if (!_private->userAgentOverridden)
    14471451        _private->userAgent = String();
     
    22882292    _private->usesPageCache = usesPageCache;
    22892293
    2290     // Post a notification so the WebCore settings update.
    2291     [[self preferences] _postPreferencesChangesNotification];
     2294    // Update our own settings and post the public notification only
     2295    [self _preferencesChanged:[self preferences]];
     2296    [[self preferences] _postPreferencesChangedAPINotification];
    22922297}
    22932298
     
    28742879
    28752880    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_applicationWillTerminate) name:NSApplicationWillTerminateNotification object:NSApp];
    2876     [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_preferencesChangedNotification:) name:WebPreferencesChangedNotification object:nil];
     2881    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_preferencesChangedNotification:) name:WebPreferencesChangedInternalNotification object:nil];
    28772882    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_preferencesRemovedNotification:) name:WebPreferencesRemovedNotification object:nil];   
    28782883
     
    33793384    WebPreferences *oldPrefs = _private->preferences;
    33803385
    3381     [[NSNotificationCenter defaultCenter] removeObserver:self name:WebPreferencesChangedNotification object:[self preferences]];
     3386    [[NSNotificationCenter defaultCenter] removeObserver:self name:WebPreferencesChangedInternalNotification object:[self preferences]];
    33823387    [WebPreferences _removeReferenceForIdentifier:[oldPrefs identifier]];
    33833388
     
    33863391    // After registering for the notification, post it so the WebCore settings update.
    33873392    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_preferencesChangedNotification:)
    3388         name:WebPreferencesChangedNotification object:[self preferences]];
    3389     [[self preferences] _postPreferencesChangesNotification];
     3393        name:WebPreferencesChangedInternalNotification object:[self preferences]];
     3394    [self _preferencesChanged:[self preferences]];
     3395    [[self preferences] _postPreferencesChangedAPINotification];
    33903396
    33913397    [oldPrefs didRemoveFromWebView];
     
    59905996        [[NSNotificationCenter defaultCenter]
    59915997            addObserver:self selector:@selector(_retrieveKeyboardUIModeFromPreferences:)
    5992             name:WebPreferencesChangedNotification object:nil];
     5998            name:WebPreferencesChangedInternalNotification object:nil];
    59935999    }
    59946000    return _private->_keyboardUIMode;
  • trunk/Source/WebKit/mac/WebView/WebViewInternal.h

    r82148 r83324  
    184184- (void)_setInsertionPasteboard:(NSPasteboard *)pasteboard;
    185185
     186- (void)_preferencesChanged:(WebPreferences *)preferences;
     187
    186188#if ENABLE(VIDEO) && defined(__cplusplus)
    187189- (void)_enterFullscreenForNode:(WebCore::Node*)node;
Note: See TracChangeset for help on using the changeset viewer.