зеркало из https://github.com/mozilla/gecko-dev.git
Enable interrupting of parsing to improve performance during long document loads + include dynamic switching between user-responsiveness and page load performance,bug 76722 sr=attinasi@netscape.com, r=harishd@netscape.com.
This commit is contained in:
Родитель
9d2900700d
Коммит
a80e214257
|
@ -174,33 +174,7 @@ static PRLogModuleInfo* gSinkLogModuleInfo;
|
|||
#define NS_SINK_FLAG_SCRIPT_ENABLED 0x8
|
||||
#define NS_SINK_FLAG_FRAMES_ENABLED 0x10
|
||||
#define NS_SINK_FLAG_CAN_INTERRUPT_PARSER 0x20 //Interrupt parsing when mMaxTokenProcessingTime is exceeded
|
||||
|
||||
// Timer used to determine how long the content sink
|
||||
// spends processing a tokens
|
||||
|
||||
class nsDelayTimer
|
||||
{
|
||||
public:
|
||||
|
||||
void Start(void) {
|
||||
mStart = PR_IntervalToMicroseconds(PR_IntervalNow());
|
||||
}
|
||||
|
||||
// Determine if the current time - start time is greater
|
||||
// then aMaxDelayInMicroseconds
|
||||
PRBool HasExceeded(PRUint32 aMaxDelayInMicroseconds) {
|
||||
PRUint32 stop = PR_IntervalToMicroseconds(PR_IntervalNow());
|
||||
if ((stop - mStart) > aMaxDelayInMicroseconds) {
|
||||
return PR_TRUE;
|
||||
}
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
private:
|
||||
PRUint32 mStart;
|
||||
};
|
||||
|
||||
|
||||
#define NS_SINK_FLAG_DYNAMIC_LOWER_VALUE 0x40 // Lower the value for mNotificationInterval and mMaxTokenProcessingTime
|
||||
|
||||
|
||||
class SinkContext;
|
||||
|
@ -347,6 +321,16 @@ public:
|
|||
nsIDOMHTMLFormElement* aForm,
|
||||
nsIWebShell* aWebShell,
|
||||
nsIHTMLContent** aResult);
|
||||
|
||||
inline PRInt32 GetNotificationInterval() {
|
||||
return ((mFlags & NS_SINK_FLAG_DYNAMIC_LOWER_VALUE) ? 1000 : mNotificationInterval);
|
||||
};
|
||||
|
||||
inline PRInt32 GetMaxTokenProcessingTime() {
|
||||
return ((mFlags & NS_SINK_FLAG_DYNAMIC_LOWER_VALUE) ? 3000 : mMaxTokenProcessingTime);
|
||||
};
|
||||
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
void SinkTraceNode(PRUint32 aBit,
|
||||
const char* aMsg,
|
||||
|
@ -407,8 +391,9 @@ public:
|
|||
PRUint32 mFlags;
|
||||
|
||||
// Can interrupt parsing members
|
||||
nsDelayTimer mDelayTimer;
|
||||
PRUint32 mDelayTimerStart;
|
||||
PRInt32 mMaxTokenProcessingTime; // Interrupt parsing during token procesing after # of microseconds
|
||||
PRInt32 mDynamicIntervalSwitchThreshold; // Switch between intervals when time is exceeded
|
||||
|
||||
void StartLayout();
|
||||
|
||||
|
@ -2518,11 +2503,14 @@ HTMLContentSink::Init(nsIDocument* aDoc,
|
|||
|
||||
mMaxTokenProcessingTime = mNotificationInterval * 3;
|
||||
|
||||
PRBool enableInterruptParsing = PR_FALSE;
|
||||
PRBool enableInterruptParsing = PR_TRUE;
|
||||
|
||||
mDynamicIntervalSwitchThreshold = 750000; // 3/4 second default for switching
|
||||
|
||||
if (prefs) {
|
||||
prefs->GetBoolPref("content.interrupt.parsing", &enableInterruptParsing);
|
||||
prefs->GetIntPref("content.max.tokenizing.time", &mMaxTokenProcessingTime);
|
||||
prefs->GetIntPref("content.switch.threshold", &mDynamicIntervalSwitchThreshold);
|
||||
}
|
||||
|
||||
if (enableInterruptParsing) {
|
||||
|
@ -2722,7 +2710,7 @@ HTMLContentSink::Notify(nsITimer *timer)
|
|||
PRInt64 diff, interval;
|
||||
PRInt32 delay;
|
||||
|
||||
LL_I2L(interval, mNotificationInterval);
|
||||
LL_I2L(interval, GetNotificationInterval());
|
||||
LL_SUB(diff, now, mLastNotificationTime);
|
||||
|
||||
LL_SUB(diff, diff, interval);
|
||||
|
@ -2757,7 +2745,7 @@ HTMLContentSink::WillInterrupt()
|
|||
PRInt64 interval, diff;
|
||||
PRInt32 delay;
|
||||
|
||||
LL_I2L(interval, mNotificationInterval);
|
||||
LL_I2L(interval, GetNotificationInterval());
|
||||
LL_SUB(diff, now, mLastNotificationTime);
|
||||
|
||||
// If it's already time for us to have a notification
|
||||
|
@ -2777,7 +2765,7 @@ HTMLContentSink::WillInterrupt()
|
|||
}
|
||||
// Else set up a timer for the expected interval
|
||||
else {
|
||||
delay = mNotificationInterval;
|
||||
delay = GetNotificationInterval();
|
||||
}
|
||||
|
||||
// Convert to milliseconds
|
||||
|
@ -3706,7 +3694,7 @@ HTMLContentSink::AddDocTypeDecl(const nsIParserNode& aNode, PRInt32 aMode)
|
|||
NS_IMETHODIMP
|
||||
HTMLContentSink::WillProcessTokens(void) {
|
||||
if (mFlags & NS_SINK_FLAG_CAN_INTERRUPT_PARSER) {
|
||||
mDelayTimer.Start();
|
||||
mDelayTimerStart = PR_IntervalToMicroseconds(PR_IntervalNow());
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -3723,8 +3711,57 @@ HTMLContentSink::WillProcessAToken(void) {
|
|||
|
||||
NS_IMETHODIMP
|
||||
HTMLContentSink::DidProcessAToken(void) {
|
||||
if ((mFlags & NS_SINK_FLAG_CAN_INTERRUPT_PARSER) && (mDelayTimer.HasExceeded(mMaxTokenProcessingTime))) {
|
||||
return NS_ERROR_HTMLPARSER_INTERRUPTED;
|
||||
|
||||
if (mFlags & NS_SINK_FLAG_CAN_INTERRUPT_PARSER) {
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
PRInt32 oldMaxTokenProcessingTime = GetMaxTokenProcessingTime();
|
||||
#endif
|
||||
|
||||
PRUint32 currentTime = PR_IntervalToMicroseconds(PR_IntervalNow());
|
||||
|
||||
// Get the last user event time and compare it with
|
||||
// the current time to determine if the lower value
|
||||
// for content notification and max token processing
|
||||
// should be used.
|
||||
if (mDocument) {
|
||||
nsCOMPtr<nsIPresShell> shell;
|
||||
mDocument->GetShellAt(0, getter_AddRefs(shell));
|
||||
if (shell) {
|
||||
nsCOMPtr<nsIViewManager> vm;
|
||||
shell->GetViewManager(getter_AddRefs(vm));
|
||||
PRUint32 eventTime;
|
||||
nsresult rv = vm->GetLastUserEventTime(eventTime);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
|
||||
if ((currentTime - eventTime) < NS_STATIC_CAST(PRUint32, mDynamicIntervalSwitchThreshold)) {
|
||||
// lower the dynamic values to favor
|
||||
// application responsiveness over page load
|
||||
// time.
|
||||
mFlags |= NS_SINK_FLAG_DYNAMIC_LOWER_VALUE;
|
||||
}
|
||||
else {
|
||||
// raise the content notification and
|
||||
// MaxTokenProcessing time to favor overall
|
||||
// page load speed over responsiveness
|
||||
mFlags &= ~NS_SINK_FLAG_DYNAMIC_LOWER_VALUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
PRInt32 newMaxTokenProcessingTime = GetMaxTokenProcessingTime();
|
||||
|
||||
if (newMaxTokenProcessingTime != oldMaxTokenProcessingTime) {
|
||||
// printf("Changed dynamic interval : MaxTokenProcessingTime %d\n", GetMaxTokenProcessingTime());
|
||||
}
|
||||
#endif
|
||||
|
||||
if ((currentTime - mDelayTimerStart) > NS_STATIC_CAST(PRUint32, GetMaxTokenProcessingTime())) {
|
||||
return NS_ERROR_HTMLPARSER_INTERRUPTED;
|
||||
}
|
||||
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -4620,7 +4657,7 @@ HTMLContentSink::IsTimeToNotify()
|
|||
PRTime now = PR_Now();
|
||||
PRInt64 interval, diff;
|
||||
|
||||
LL_I2L(interval, mNotificationInterval);
|
||||
LL_I2L(interval, GetNotificationInterval());
|
||||
LL_SUB(diff, now, mLastNotificationTime);
|
||||
|
||||
if (LL_CMP(diff, >, interval)) {
|
||||
|
|
|
@ -526,6 +526,15 @@ public:
|
|||
* @param aColor the default background color
|
||||
*/
|
||||
NS_IMETHOD GetDefaultBackgroundColor(nscolor* aColor)=0;
|
||||
|
||||
/**
|
||||
* Retrieve the time of the last user event. User events
|
||||
* include mouse and keyboard events. The viewmanager
|
||||
* saves the time of the last user event.
|
||||
*
|
||||
* @param aTime Last user event time in microseconds
|
||||
*/
|
||||
NS_IMETHOD GetLastUserEventTime(PRUint32& aTime)=0;
|
||||
};
|
||||
|
||||
//when the refresh happens, should it be double buffered?
|
||||
|
|
|
@ -396,6 +396,7 @@ nsSize nsViewManager::gLargestRequestedSize = nsSize(0, 0);
|
|||
|
||||
// Weakly held references to all of the view managers
|
||||
nsVoidArray* nsViewManager::gViewManagers = nsnull;
|
||||
PRUint32 nsViewManager::gLastUserEventTime = 0;
|
||||
|
||||
static NS_DEFINE_IID(knsViewManagerIID, NS_IVIEWMANAGER_IID);
|
||||
|
||||
|
@ -1978,12 +1979,16 @@ NS_IMETHODIMP nsViewManager::DispatchEvent(nsGUIEvent *aEvent, nsEventStatus *aS
|
|||
nsPoint offset;
|
||||
nsIScrollbar* sb;
|
||||
|
||||
if (NS_IS_MOUSE_EVENT(aEvent) || NS_IS_KEY_EVENT(aEvent)) {
|
||||
gLastUserEventTime = PR_IntervalToMicroseconds(PR_IntervalNow());
|
||||
}
|
||||
|
||||
//Find the view whose coordinates system we're in.
|
||||
baseView = nsView::GetViewFor(aEvent->widget);
|
||||
|
||||
//Find the view to which we're initially going to send the event
|
||||
//for hittesting.
|
||||
if (nsnull != mMouseGrabber && (NS_IS_MOUSE_EVENT(aEvent) || NS_IS_DRAG_EVENT(aEvent))) {
|
||||
if (nsnull != mMouseGrabber && (NS_IS_MOUSE_EVENT(aEvent) || (NS_IS_DRAG_EVENT(aEvent)))) {
|
||||
view = mMouseGrabber;
|
||||
}
|
||||
else if (nsnull != mKeyGrabber && NS_IS_KEY_EVENT(aEvent)) {
|
||||
|
@ -2724,6 +2729,7 @@ PRInt32 nsViewManager::GetViewManagerCount()
|
|||
return mVMCount;
|
||||
}
|
||||
|
||||
|
||||
const nsVoidArray* nsViewManager::GetViewManagerArray()
|
||||
{
|
||||
return gViewManagers;
|
||||
|
@ -3858,3 +3864,14 @@ nsViewManager::GetDefaultBackgroundColor(nscolor* aColor)
|
|||
*aColor = mDefaultBackgroundColor;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsViewManager::GetLastUserEventTime(PRUint32& aTime)
|
||||
{
|
||||
aTime = gLastUserEventTime;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -156,9 +156,11 @@ public:
|
|||
NS_IMETHOD FlushPendingInvalidates();
|
||||
NS_IMETHOD SetDefaultBackgroundColor(nscolor aColor);
|
||||
NS_IMETHOD GetDefaultBackgroundColor(nscolor* aColor);
|
||||
NS_IMETHOD GetLastUserEventTime(PRUint32& aTime);
|
||||
nsresult ProcessInvalidateEvent();
|
||||
static PRInt32 GetViewManagerCount();
|
||||
static const nsVoidArray* GetViewManagerArray();
|
||||
static PRUint32 gLastUserEventTime;
|
||||
protected:
|
||||
virtual ~nsViewManager();
|
||||
void ProcessPendingUpdates(nsIView *aView);
|
||||
|
|
|
@ -2979,3 +2979,12 @@ nsViewManager2::GetDefaultBackgroundColor(nscolor* aColor)
|
|||
*aColor = 0;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsViewManager2::GetLastUserEventTime(PRUint32& aTime)
|
||||
{
|
||||
aTime = 0;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -153,6 +153,7 @@ public:
|
|||
NS_IMETHOD FlushPendingInvalidates();
|
||||
NS_IMETHOD SetDefaultBackgroundColor(nscolor aColor);
|
||||
NS_IMETHOD GetDefaultBackgroundColor(nscolor* aColor);
|
||||
NS_IMETHOD GetLastUserEventTime(PRUint32& aTime);
|
||||
nsresult ProcessInvalidateEvent();
|
||||
static PRInt32 GetViewManagerCount();
|
||||
static const nsVoidArray* GetViewManagerArray();
|
||||
|
|
Загрузка…
Ссылка в новой задаче