From 1fc89bc8e9f0549e05a52837d6af6c1a7a1b4564 Mon Sep 17 00:00:00 2001 From: "kmcclusk%netscape.com" Date: Thu, 19 Sep 2002 02:53:05 +0000 Subject: [PATCH] Change PLEvent notification on WIN32 to use a native timer instead of a posted WM_APP message when documents are not loading. This fixes some DHTML paint starvation issues and lowers overall CPU usage on many pages with DHTML. bug=164931 r=rpotts@netscape.com sr=kin@netscape.com git-svn-id: svn://10.0.0.236/trunk@130007 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/docshell/base/nsDocShell.cpp | 29 ++++++++++++++++++++ mozilla/xpcom/threads/plevent.c | 41 +++++++++++++++++++++------- mozilla/xpcom/threads/plevent.h | 16 +++++++++++ 3 files changed, 76 insertions(+), 10 deletions(-) diff --git a/mozilla/docshell/base/nsDocShell.cpp b/mozilla/docshell/base/nsDocShell.cpp index 14c0fa1acfd..faef688d409 100644 --- a/mozilla/docshell/base/nsDocShell.cpp +++ b/mozilla/docshell/base/nsDocShell.cpp @@ -145,6 +145,17 @@ static NS_DEFINE_CID(kDOMScriptObjectFactoryCID, #if defined(DEBUG_rods) || defined(DEBUG_bryner) //#define DEBUG_DOCSHELL_FOCUS #endif + +#include "plevent.h" + +// Number of documents currently loading +static PRInt32 gNumberOfDocumentsLoading = 0; + +// Hint for native dispatch of plevents on how long to delay after +// all documents have loaded in milliseconds before favoring normal +// native event dispatch priorites over performance +#define NS_EVENT_STARVATION_DELAY_HINT 2000 + // // Local function prototypes // @@ -4118,6 +4129,14 @@ nsDocShell::EndPageLoad(nsIWebProgress * aProgress, mContentViewer->LoadComplete(aStatus); mEODForCurrentDocument = PR_TRUE; + + // If all documents have completed their loading + // favor native event dispatch priorities + // over performance + if (--gNumberOfDocumentsLoading == 0) { + // Hint to use normal native event dispatch priorities + PL_FavorPerformanceHint(PR_FALSE, NS_EVENT_STARVATION_DELAY_HINT); + } } /* Check if the httpChannel has any cache-control related response headers, * like no-store, no-cache. If so, update SHEntry so that @@ -4321,6 +4340,16 @@ nsDocShell::CreateContentViewer(const char *aContentType, mEODForCurrentDocument = PR_FALSE; + // Give hint to native plevent dispatch mechanism. If a document + // is loading the native plevent dispatch mechanism should favor + // performance over normal native event dispatch priorities. + if (++gNumberOfDocumentsLoading == 1) { + // Hint to favor performance for the plevent notification mechanism. + // We want the pages to load as fast as possible even if its means + // native messages might be starved. + PL_FavorPerformanceHint(PR_TRUE, NS_EVENT_STARVATION_DELAY_HINT); + } + return NS_OK; } diff --git a/mozilla/xpcom/threads/plevent.c b/mozilla/xpcom/threads/plevent.c index 0920c05e5d0..6ea2ef4f296 100644 --- a/mozilla/xpcom/threads/plevent.c +++ b/mozilla/xpcom/threads/plevent.c @@ -99,9 +99,12 @@ #define WIN9X_PAINT_STARVATION_LIMIT 3000 #define TIMER_ID 0 -static HHOOK _md_MouseMsgFilterHook = NULL; -static PRBool _md_MovingWindow = PR_FALSE; -static PRInt32 _md_WindowCount = 0; +static HHOOK _md_MouseMsgFilterHook = NULL; +static PRBool _md_MovingWindow = PR_FALSE; +static PRInt32 _md_WindowCount = 0; +static PRBool _md_FavorPerformance = PR_FALSE; +static PRUint32 _md_StarvationDelay = 0; +static PRUint32 _md_SwitchTime = 0; #endif static PRLogModuleInfo *event_lm = NULL; @@ -714,6 +717,19 @@ PL_DequeueEvent(PLEvent* self, PLEventQueue* queue) PR_ExitMonitor(queue->monitor); } +PR_IMPLEMENT(void) +PL_FavorPerformanceHint(PRBool favorPerformanceOverEventStarvation, PRUint32 starvationDelay) +{ +#if defined(_WIN32) + _md_FavorPerformance = favorPerformanceOverEventStarvation; + _md_StarvationDelay = starvationDelay; + + if (! favorPerformanceOverEventStarvation) { + _md_SwitchTime = PR_IntervalToMilliseconds(PR_IntervalNow()); + } +#endif +} + /******************************************************************************* * Pure Event Queues * @@ -955,16 +971,16 @@ static PRUint32 _md_GetPaintStarvationLimit() { */ static PRBool _md_EventIsStarved(PRBool isPending, PRUint32 starvationLimit, - PRBool *wasPending, PRUint32 *lastTime) + PRBool *wasPending, PRUint32 *lastTime, + PRUint32 currentTime) { if ((*wasPending) && (isPending)) { /* It was pending previously and the event is still * pending so check to see if the elapsed time is * over the limit which indicates the event was starved */ - PRUint32 now = PR_IntervalToMilliseconds(PR_IntervalNow()); - if ((now - *lastTime) > starvationLimit) { + if ((currentTime - *lastTime) > starvationLimit) { return PR_TRUE; /* pending and over the limit */ } @@ -976,7 +992,7 @@ static PRBool _md_EventIsStarved(PRBool isPending, PRUint32 starvationLimit, * so the elapsed time can be computed the next time this * function is called */ - *lastTime = PR_IntervalToMilliseconds(PR_IntervalNow()); + *lastTime = currentTime; *wasPending = PR_TRUE; return PR_FALSE; } @@ -1030,11 +1046,16 @@ _pl_NativeNotify(PLEventQueue* self) #ifdef USE_TIMER WORD qstatus; - if (_md_MovingWindow) { + PRUint32 now = PR_IntervalToMilliseconds(PR_IntervalNow()); + + if (_md_MovingWindow || + (! _md_FavorPerformance) && + ((now - _md_SwitchTime) > _md_StarvationDelay)) { SetTimer(self->eventReceiverWindow, TIMER_ID, 0 ,_md_TimerProc); self->timerSet = PR_TRUE; _md_WasInputPending = PR_FALSE; _md_WasPaintPending = PR_FALSE; + return PR_SUCCESS; } @@ -1042,7 +1063,7 @@ _pl_NativeNotify(PLEventQueue* self) /* Check for starved input */ if (_md_EventIsStarved( _md_IsInputPending(qstatus), INPUT_STARVATION_LIMIT, - &_md_WasInputPending, &_md_InputTime )) { + &_md_WasInputPending, &_md_InputTime, now )) { /* Use timer for notification. Timers have the lowest priority. They are not processed * until all other events have been processed. This allows the starved paints and input to * be processed @@ -1055,7 +1076,7 @@ _pl_NativeNotify(PLEventQueue* self) } if (_md_EventIsStarved( (qstatus & QS_PAINT), _md_GetPaintStarvationLimit(), - &_md_WasPaintPending, &_md_PaintTime) ) { + &_md_WasPaintPending, &_md_PaintTime, now) ) { /* Use timer for notification. Timers have the lowest priority. They are not processed * until all other events have been processed. This allows the starved paints and input to * be processed diff --git a/mozilla/xpcom/threads/plevent.h b/mozilla/xpcom/threads/plevent.h index 70fd43363b2..58bdc00ff1b 100644 --- a/mozilla/xpcom/threads/plevent.h +++ b/mozilla/xpcom/threads/plevent.h @@ -458,6 +458,22 @@ PL_DestroyEvent(PLEvent* self); PR_EXTERN(void) PL_DequeueEvent(PLEvent* self, PLEventQueue* queue); + +/* + * Give hint to native PL_Event notification mechanism. If the native + * platform needs to tradeoff performance vs. native event starvation + * this hint tells the native dispatch code which to favor. + * The default is to prevent event starvation. + * + * The starvationDelay arg is only used when + * favorPerformanceOverEventStarvation is PR_FALSE. It is the + * amount of time in milliseconds to wait before the PR_FALSE actually + * takes effect. + */ +PR_EXTERN(void) +PL_FavorPerformanceHint(PRBool favorPerformanceOverEventStarvation, PRUint32 starvationDelay); + + /******************************************************************************* * Private Stuff ******************************************************************************/