Be smarter about searching the array of elements seen in this append batch in HTML5 parsing

This commit is contained in:
Henri Sivonen 2009-03-04 16:36:52 +02:00
parent 2c98cfad79
commit c1c7b938f9
2 changed files with 33 additions and 31 deletions

View File

@ -256,6 +256,9 @@ nsHtml5TreeBuilder::end()
#ifdef DEBUG_hsivonen #ifdef DEBUG_hsivonen
printf("MAX INSERTION BATCH LEN: %d\n", sInsertionBatchMaxLength); printf("MAX INSERTION BATCH LEN: %d\n", sInsertionBatchMaxLength);
printf("MAX NOTIFICATION BATCH LEN: %d\n", sAppendBatchMaxSize); printf("MAX NOTIFICATION BATCH LEN: %d\n", sAppendBatchMaxSize);
if (sAppendBatchExaminations != 0) {
printf("AVERAGE SLOTS EXAMINED: %d\n", sAppendBatchSlotsExamined / sAppendBatchExaminations);
}
#endif #endif
} }
@ -445,15 +448,18 @@ nsHtml5TreeBuilder::Flush()
{ {
if (!mFlushing) { if (!mFlushing) {
mFlushing = PR_TRUE; mFlushing = PR_TRUE;
PRUint32 opQueueLength = mOpQueue.Length();
mElementsSeenInThisAppendBatch.SetCapacity(opQueueLength * 2);
// XXX alloc failure
const nsHtml5TreeOperation* start = mOpQueue.Elements(); const nsHtml5TreeOperation* start = mOpQueue.Elements();
const nsHtml5TreeOperation* end = start + mOpQueue.Length(); const nsHtml5TreeOperation* end = start + opQueueLength;
for (nsHtml5TreeOperation* iter = (nsHtml5TreeOperation*)start; iter < end; ++iter) { for (nsHtml5TreeOperation* iter = (nsHtml5TreeOperation*)start; iter < end; ++iter) {
iter->Perform(this); iter->Perform(this);
} }
FlushPendingAppendNotifications(); FlushPendingAppendNotifications();
#ifdef DEBUG_hsivonen #ifdef DEBUG_hsivonen
if (mOpQueue.Length() > sInsertionBatchMaxLength) { if (mOpQueue.Length() > sInsertionBatchMaxLength) {
sInsertionBatchMaxLength = mOpQueue.Length(); sInsertionBatchMaxLength = opQueueLength;
} }
#endif #endif
mOpQueue.Clear(); mOpQueue.Clear();
@ -464,5 +470,7 @@ nsHtml5TreeBuilder::Flush()
#ifdef DEBUG_hsivonen #ifdef DEBUG_hsivonen
PRUint32 nsHtml5TreeBuilder::sInsertionBatchMaxLength = 0; PRUint32 nsHtml5TreeBuilder::sInsertionBatchMaxLength = 0;
PRUint32 nsHtml5TreeBuilder::sAppendBatchMaxSize = 0; PRUint32 nsHtml5TreeBuilder::sAppendBatchMaxSize = 0;
PRUint32 nsHtml5TreeBuilder::sAppendBatchSlotsExamined = 0;
PRUint32 nsHtml5TreeBuilder::sAppendBatchExaminations = 0;
#endif #endif

View File

@ -39,6 +39,8 @@
#ifdef DEBUG_hsivonen #ifdef DEBUG_hsivonen
static PRUint32 sInsertionBatchMaxLength; static PRUint32 sInsertionBatchMaxLength;
static PRUint32 sAppendBatchMaxSize; static PRUint32 sAppendBatchMaxSize;
static PRUint32 sAppendBatchSlotsExamined;
static PRUint32 sAppendBatchExaminations;
#endif #endif
nsHtml5Parser* mParser; // weak ref nsHtml5Parser* mParser; // weak ref
PRBool mHasProcessedBase; PRBool mHasProcessedBase;
@ -53,38 +55,30 @@
void Flush(); void Flush();
inline void PostPendingAppendNotification(nsIContent* aParent, nsIContent* aChild) { inline void PostPendingAppendNotification(nsIContent* aParent, nsIContent* aChild) {
nsIContent* parent = aParent; // this gets nulled when found PRBool newParent = PR_TRUE;
nsIContent* child = aChild->IsNodeOfType(nsINode::eELEMENT) ? aChild : nsnull; // this gets nulled when found const nsIContentPtr* first = mElementsSeenInThisAppendBatch.Elements();
const nsIContentPtr* start = mElementsSeenInThisAppendBatch.Elements(); const nsIContentPtr* last = first + (mElementsSeenInThisAppendBatch.Length() - 1);
const nsIContentPtr* end = start + mElementsSeenInThisAppendBatch.Length(); for (const nsIContentPtr* iter = last; iter >= first; --iter) {
// XXX backwards iterate #ifdef DEBUG_hsivonen
for (const nsIContentPtr* iter = start; iter < end; ++iter) { sAppendBatchSlotsExamined++;
if (*iter == parent) { #endif
parent = nsnull; if (*iter == aParent) {
} newParent = PR_FALSE;
if (*iter == child) {
child = nsnull;
}
if (!(parent || child)) {
break; break;
} }
} }
if (child) { if (aChild->IsNodeOfType(nsINode::eELEMENT)) {
mElementsSeenInThisAppendBatch.AppendElement(child); mElementsSeenInThisAppendBatch.AppendElement(aChild);
} }
if (parent) { mElementsSeenInThisAppendBatch.AppendElement(aParent);
// parents that are in mPendingNotifications don't need to be added to if (newParent) {
// mElementsSeenInThisAppendBatch mPendingNotifications.AppendElement(aParent);
const nsHtml5PendingNotification* startNotifications = mPendingNotifications.Elements();
const nsHtml5PendingNotification* endNotifications = startNotifications + mPendingNotifications.Length();
// XXX backwards iterate
for (nsHtml5PendingNotification* iter = (nsHtml5PendingNotification*)startNotifications; iter < endNotifications; ++iter) {
if (iter->Contains(parent)) {
return;
}
}
mPendingNotifications.AppendElement(parent);
} }
#ifdef DEBUG_hsivonen
sAppendBatchExaminations++;
#endif
} }
inline void FlushPendingAppendNotifications() { inline void FlushPendingAppendNotifications() {