Reviewed by John Sullivan.
authortomernic <tomernic@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 12 May 2006 17:40:42 +0000 (17:40 +0000)
committertomernic <tomernic@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 12 May 2006 17:40:42 +0000 (17:40 +0000)
        <rdar://problem/4542808> REGRESSION: benchjs test 1 has slowed by over 150% (8740)
        <http://bugzilla.opendarwin.org/show_bug.cgi?id=8740>

        Improvement to my NSWindow display throttle hack.  Remember the last flush time instead of the last display time.
        Our goal is to never draw less than 1/60th of a second after the window is flushed in order to avoid blocking on
        a CG coalesced update.  Using the last display time is close, but this is much more accurate.  I have verified that
        this further improves our score on BenchJS Test 1 (by 9.8% with the status bar shown compared to the previous build),
        as well as on our internal PLT scores by a smaller percentage.

        * Misc/WebNSWindowExtras.m:
        Renamed lastDisplayTime to lastFlushTime.
        (+[NSWindow _webkit_enableWindowDisplayThrottle]):
        Replace -[NSWindow flushWindow] with our own implementation.
        (+[NSWindow _webkit_disableWindowDisplayThrottle]):
        Restore -[NSWindow flushWindow].
        (replacementFlushWindow):
        Use the last flush time instead of the last display time.
        (getWindowDisplayInfo):
        Renamed lastDisplayTime to lastFlushTime.
        (requestWindowDisplay):
        Moved some code to replacementFlushWindow().

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@14325 268f45cc-cd09-0410-ab3c-d52691b4dbfc

WebKit/ChangeLog
WebKit/Misc/WebNSWindowExtras.m

index d92f92ae55f16ea11447df0b2092d325e33784b5..235535f6c73b451e0e91633936d53a0730623871 100644 (file)
@@ -1,3 +1,29 @@
+2006-05-12  Tim Omernick  <timo@apple.com>
+
+        Reviewed by John Sullivan.
+
+        <rdar://problem/4542808> REGRESSION: benchjs test 1 has slowed by over 150% (8740)
+        <http://bugzilla.opendarwin.org/show_bug.cgi?id=8740>
+
+        Improvement to my NSWindow display throttle hack.  Remember the last flush time instead of the last display time.
+        Our goal is to never draw less than 1/60th of a second after the window is flushed in order to avoid blocking on
+        a CG coalesced update.  Using the last display time is close, but this is much more accurate.  I have verified that
+        this further improves our score on BenchJS Test 1 (by 9.8% with the status bar shown compared to the previous build),
+        as well as on our internal PLT scores by a smaller percentage.
+
+        * Misc/WebNSWindowExtras.m:
+        Renamed lastDisplayTime to lastFlushTime.
+        (+[NSWindow _webkit_enableWindowDisplayThrottle]):
+        Replace -[NSWindow flushWindow] with our own implementation.
+        (+[NSWindow _webkit_disableWindowDisplayThrottle]):
+        Restore -[NSWindow flushWindow].
+        (replacementFlushWindow):
+        Use the last flush time instead of the last display time.
+        (getWindowDisplayInfo):
+        Renamed lastDisplayTime to lastFlushTime.
+        (requestWindowDisplay):
+        Moved some code to replacementFlushWindow().
+
 2006-05-11  Timothy Hatcher  <timothy@apple.com>
 
         Reviewed by Darin.
index 391a6137b722f90ddad8aead7725efc7589018cc..7c940d080e0a925eb2ad26ab39c33dce88583488 100644 (file)
@@ -38,10 +38,11 @@ static BOOL throttlingWindowDisplay;
 static CFMutableDictionaryRef windowDisplayInfoDictionary;
 static IMP oldNSWindowPostWindowNeedsDisplayIMP;
 static IMP oldNSWindowCloseIMP;
+static IMP oldNSWindowFlushWindowIMP;
 
 typedef struct {
     NSWindow *window;
-    CFTimeInterval lastDisplayTime;
+    CFTimeInterval lastFlushTime;
     NSTimer *displayTimer;
 } WindowDisplayInfo;
 
@@ -49,6 +50,7 @@ typedef struct {
 static IMP swizzleInstanceMethod(Class class, SEL selector, IMP newImplementation);
 static void replacementPostWindowNeedsDisplay(id self, SEL cmd);
 static void replacementClose(id self, SEL cmd);
+static void replacementFlushWindow(id self, SEL cmd);
 static WindowDisplayInfo *getWindowDisplayInfo(NSWindow *window);
 static BOOL requestWindowDisplay(NSWindow *window);
 static void cancelPendingWindowDisplay(WindowDisplayInfo *displayInfo);
@@ -78,6 +80,11 @@ static void cancelPendingWindowDisplay(WindowDisplayInfo *displayInfo);
     ASSERT(!oldNSWindowCloseIMP);
     oldNSWindowCloseIMP = swizzleInstanceMethod(self, @selector(close), (IMP)replacementClose);
     ASSERT(oldNSWindowCloseIMP);
+
+    // Override -[NSWindow flushWindow]    
+    ASSERT(!oldNSWindowFlushWindowIMP);
+    oldNSWindowFlushWindowIMP = swizzleInstanceMethod(self, @selector(flushWindow), (IMP)replacementFlushWindow);
+    ASSERT(oldNSWindowFlushWindowIMP);
     
 //    NSLog(@"Throttling window display to %.3f times per second", 1.0 / DISPLAY_REFRESH_INTERVAL);
     
@@ -116,6 +123,11 @@ static void disableWindowDisplayThrottleApplierFunction(const void *key, const v
     swizzleInstanceMethod(self, @selector(close), oldNSWindowCloseIMP);
     oldNSWindowCloseIMP = NULL;
 
+    // Restore -[NSWindow flushWindow]    
+    ASSERT(oldNSWindowFlushWindowIMP);
+    swizzleInstanceMethod(self, @selector(flushWindow), oldNSWindowFlushWindowIMP);
+    oldNSWindowFlushWindowIMP = NULL;
+
     CFDictionaryApplyFunction(windowDisplayInfoDictionary, disableWindowDisplayThrottleApplierFunction, NULL);
     CFRelease(windowDisplayInfoDictionary);
     windowDisplayInfoDictionary = NULL;
@@ -186,6 +198,14 @@ static void replacementClose(id self, SEL cmd)
     oldNSWindowCloseIMP(self, cmd);
 }
 
+static void replacementFlushWindow(id self, SEL cmd)
+{
+    ASSERT(throttlingWindowDisplay);
+
+    oldNSWindowFlushWindowIMP(self, cmd);
+    getWindowDisplayInfo(self)->lastFlushTime = CFAbsoluteTimeGetCurrent();
+}
+
 static WindowDisplayInfo *getWindowDisplayInfo(NSWindow *window)
 {
     ASSERT(throttlingWindowDisplay);
@@ -196,7 +216,7 @@ static WindowDisplayInfo *getWindowDisplayInfo(NSWindow *window)
     if (!displayInfo) {
         displayInfo = (WindowDisplayInfo *)malloc(sizeof(WindowDisplayInfo));
         displayInfo->window = window;
-        displayInfo->lastDisplayTime = 0;
+        displayInfo->lastFlushTime = 0;
         displayInfo->displayTimer = nil;
         CFDictionarySetValue(windowDisplayInfoDictionary, window, displayInfo);
     }
@@ -215,7 +235,7 @@ static BOOL requestWindowDisplay(NSWindow *window)
         
     // Defer display if it hasn't been at least DISPLAY_REFRESH_INTERVAL seconds since the last display
     CFTimeInterval now = CFAbsoluteTimeGetCurrent();
-    CFTimeInterval timeSinceLastDisplay = now - displayInfo->lastDisplayTime;
+    CFTimeInterval timeSinceLastDisplay = now - displayInfo->lastFlushTime;
     if (timeSinceLastDisplay < DISPLAY_REFRESH_INTERVAL) {
         // Redisplay soon -- if we redisplay too quickly, we'll block due to pending CG coalesced updates
         displayInfo->displayTimer = [[NSTimer timerWithTimeInterval:(DISPLAY_REFRESH_INTERVAL - timeSinceLastDisplay)
@@ -233,8 +253,6 @@ static BOOL requestWindowDisplay(NSWindow *window)
         return NO;
     }
 
-    // Allow the display: there is no pending display, and it's been long enough to display again.
-    displayInfo->lastDisplayTime = now;
     return YES;
 }