From c1c7b938f91d80d9453d93ab41ea3cc7117a8d45 Mon Sep 17 00:00:00 2001 From: Henri Sivonen Date: Wed, 4 Mar 2009 16:36:52 +0200 Subject: [PATCH] Be smarter about searching the array of elements seen in this append batch in HTML5 parsing --- .../src/nsHtml5TreeBuilderCppSupplement.h | 12 ++++- .../src/nsHtml5TreeBuilderHSupplement.h | 52 ++++++++----------- 2 files changed, 33 insertions(+), 31 deletions(-) diff --git a/content/html/parser/src/nsHtml5TreeBuilderCppSupplement.h b/content/html/parser/src/nsHtml5TreeBuilderCppSupplement.h index e28da82400b..ca2a06eae15 100644 --- a/content/html/parser/src/nsHtml5TreeBuilderCppSupplement.h +++ b/content/html/parser/src/nsHtml5TreeBuilderCppSupplement.h @@ -256,6 +256,9 @@ nsHtml5TreeBuilder::end() #ifdef DEBUG_hsivonen printf("MAX INSERTION BATCH LEN: %d\n", sInsertionBatchMaxLength); printf("MAX NOTIFICATION BATCH LEN: %d\n", sAppendBatchMaxSize); + if (sAppendBatchExaminations != 0) { + printf("AVERAGE SLOTS EXAMINED: %d\n", sAppendBatchSlotsExamined / sAppendBatchExaminations); + } #endif } @@ -445,15 +448,18 @@ nsHtml5TreeBuilder::Flush() { if (!mFlushing) { mFlushing = PR_TRUE; + PRUint32 opQueueLength = mOpQueue.Length(); + mElementsSeenInThisAppendBatch.SetCapacity(opQueueLength * 2); + // XXX alloc failure const nsHtml5TreeOperation* start = mOpQueue.Elements(); - const nsHtml5TreeOperation* end = start + mOpQueue.Length(); + const nsHtml5TreeOperation* end = start + opQueueLength; for (nsHtml5TreeOperation* iter = (nsHtml5TreeOperation*)start; iter < end; ++iter) { iter->Perform(this); } FlushPendingAppendNotifications(); #ifdef DEBUG_hsivonen if (mOpQueue.Length() > sInsertionBatchMaxLength) { - sInsertionBatchMaxLength = mOpQueue.Length(); + sInsertionBatchMaxLength = opQueueLength; } #endif mOpQueue.Clear(); @@ -464,5 +470,7 @@ nsHtml5TreeBuilder::Flush() #ifdef DEBUG_hsivonen PRUint32 nsHtml5TreeBuilder::sInsertionBatchMaxLength = 0; PRUint32 nsHtml5TreeBuilder::sAppendBatchMaxSize = 0; +PRUint32 nsHtml5TreeBuilder::sAppendBatchSlotsExamined = 0; +PRUint32 nsHtml5TreeBuilder::sAppendBatchExaminations = 0; #endif diff --git a/content/html/parser/src/nsHtml5TreeBuilderHSupplement.h b/content/html/parser/src/nsHtml5TreeBuilderHSupplement.h index 832a31a04fd..9f5a1bfa679 100644 --- a/content/html/parser/src/nsHtml5TreeBuilderHSupplement.h +++ b/content/html/parser/src/nsHtml5TreeBuilderHSupplement.h @@ -39,6 +39,8 @@ #ifdef DEBUG_hsivonen static PRUint32 sInsertionBatchMaxLength; static PRUint32 sAppendBatchMaxSize; + static PRUint32 sAppendBatchSlotsExamined; + static PRUint32 sAppendBatchExaminations; #endif nsHtml5Parser* mParser; // weak ref PRBool mHasProcessedBase; @@ -53,38 +55,30 @@ void Flush(); inline void PostPendingAppendNotification(nsIContent* aParent, nsIContent* aChild) { - nsIContent* parent = aParent; // this gets nulled when found - nsIContent* child = aChild->IsNodeOfType(nsINode::eELEMENT) ? aChild : nsnull; // this gets nulled when found - const nsIContentPtr* start = mElementsSeenInThisAppendBatch.Elements(); - const nsIContentPtr* end = start + mElementsSeenInThisAppendBatch.Length(); - // XXX backwards iterate - for (const nsIContentPtr* iter = start; iter < end; ++iter) { - if (*iter == parent) { - parent = nsnull; - } - if (*iter == child) { - child = nsnull; - } - if (!(parent || child)) { + PRBool newParent = PR_TRUE; + const nsIContentPtr* first = mElementsSeenInThisAppendBatch.Elements(); + const nsIContentPtr* last = first + (mElementsSeenInThisAppendBatch.Length() - 1); + for (const nsIContentPtr* iter = last; iter >= first; --iter) { +#ifdef DEBUG_hsivonen + sAppendBatchSlotsExamined++; +#endif + if (*iter == aParent) { + newParent = PR_FALSE; break; - } - } - if (child) { - mElementsSeenInThisAppendBatch.AppendElement(child); - } - if (parent) { - // parents that are in mPendingNotifications don't need to be added to - // mElementsSeenInThisAppendBatch - 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); } + if (aChild->IsNodeOfType(nsINode::eELEMENT)) { + mElementsSeenInThisAppendBatch.AppendElement(aChild); + } + mElementsSeenInThisAppendBatch.AppendElement(aParent); + if (newParent) { + mPendingNotifications.AppendElement(aParent); + } + +#ifdef DEBUG_hsivonen + sAppendBatchExaminations++; +#endif + } inline void FlushPendingAppendNotifications() {