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:
kmcclusk%netscape.com 2001-06-29 04:01:26 +00:00
Родитель 9d2900700d
Коммит a80e214257
6 изменённых файлов: 112 добавлений и 37 удалений

Просмотреть файл

@ -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();