Changeset 77050 in webkit
- Timestamp:
- Jan 28, 2011 11:37:58 PM (13 years ago)
- Location:
- trunk
- Files:
-
- 2 added
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/PerformanceTests/Parser/ChangeLog
r74825 r77050 1 2011-01-28 Eric Seidel <eric@webkit.org> 2 3 Reviewed by Darin Adler. 4 5 HTML5 TreeBuilder regressed a Peacekeeper DOM test by 40% 6 https://bugs.webkit.org/show_bug.cgi?id=48719 7 8 It's unclear exactly what the Peacekeeper benchmark is testing, 9 because I haven't found a way to run it myself. 10 11 However, I constructed a benchmark which shows at least one possible slow point. 12 The HTML5 spec talks about creating a new document for every time we use 13 the fragment parsing algorithm. Document() it turns out, it a huge bloated 14 mess, and the constructor and destructor do a huge amount of work. 15 To avoid constructing (or destructing) documents for each innerHTML call, 16 this patch adds a shared dummy document used by all innerHTML calls. 17 18 * benchmarks/parser/tiny-innerHTML.html: Added. 19 1 20 2010-12-31 Adam Barth <abarth@webkit.org> 2 21 -
trunk/Source/WebCore/ChangeLog
r77049 r77050 1 2011-01-28 Eric Seidel <eric@webkit.org> 2 3 Reviewed by Darin Adler. 4 5 HTML5 TreeBuilder regressed a Peacekeeper DOM test by 40% 6 https://bugs.webkit.org/show_bug.cgi?id=48719 7 8 It's unclear exactly what the Peacekeeper benchmark is testing, 9 because I haven't found a way to run it myself. 10 11 However, I constructed a benchmark which shows at least one possible slow point. 12 The HTML5 spec talks about creating a new document for every time we use 13 the fragment parsing algorithm. Document() it turns out, it a huge bloated 14 mess, and the constructor and destructor do a huge amount of work. 15 To avoid constructing (or destructing) documents for each innerHTML call, 16 this patch adds a shared dummy document used by all innerHTML calls. 17 18 This patch brings us from 7x slower than Safari 5 on tiny-innerHTML 19 to only 1.5x slower than Safari 5. I'm sure there is more work to do here. 20 21 Saving a shared Document like this is error prone. Currently 22 DummyDocumentFactory::releaseDocument() calls removeAllChildren() 23 in an attempt to clear the Document's state. However it's possible 24 that that call is not sufficient and we'll have future bugs here. 25 26 * html/parser/HTMLTreeBuilder.cpp: 27 (WebCore::DummyDocumentFactory::createDummyDocument): 28 (WebCore::DummyDocumentFactory::releaseDocument): 29 (WebCore::HTMLTreeBuilder::FragmentParsingContext::FragmentParsingContext): 30 (WebCore::HTMLTreeBuilder::FragmentParsingContext::document): 31 (WebCore::HTMLTreeBuilder::FragmentParsingContext::finished): 32 * html/parser/HTMLTreeBuilder.h: 33 1 34 2011-01-28 Johnny Ding <jnd@chromium.org> 2 35 -
trunk/Source/WebCore/html/parser/HTMLTreeBuilder.cpp
r76248 r77050 396 396 } 397 397 398 // NOTE: HTML5 requires that we use a dummy document when parsing 399 // document fragments. However, creating a new Document element 400 // for each fragment is very slow (Document() does too much work, and 401 // innerHTML is a common call). So we use a shared dummy document. 402 // This sharing works because there can only ever be one fragment 403 // parser at any time. Fragment parsing is synchronous and done 404 // only from the main thread. It should be impossible for javascript 405 // (or anything else) to ever hold a reference to the dummy document. 406 // See https://bugs.webkit.org/show_bug.cgi?id=48719 407 class DummyDocumentFactory { 408 WTF_MAKE_NONCOPYABLE(DummyDocumentFactory); WTF_MAKE_FAST_ALLOCATED; 409 public: 410 // Use an explicit create/release here to ASSERT this sharing is safe. 411 static HTMLDocument* createDummyDocument(); 412 static void releaseDocument(HTMLDocument*); 413 414 private: 415 static HTMLDocument* s_sharedDummyDocument; 416 static int s_sharedDummyDocumentMutex; 417 }; 418 419 HTMLDocument* DummyDocumentFactory::createDummyDocument() 420 { 421 if (!s_sharedDummyDocument) { 422 s_sharedDummyDocument = HTMLDocument::create(0, KURL()).releaseRef(); 423 s_sharedDummyDocumentMutex = 0; 424 } 425 ASSERT(!s_sharedDummyDocumentMutex); 426 ASSERT(!s_sharedDummyDocument->hasChildNodes()); 427 s_sharedDummyDocumentMutex++; 428 return s_sharedDummyDocument; 429 } 430 431 void DummyDocumentFactory::releaseDocument(HTMLDocument* dummyDocument) 432 { 433 ASSERT(s_sharedDummyDocument == dummyDocument); 434 s_sharedDummyDocumentMutex--; 435 ASSERT(!s_sharedDummyDocumentMutex); 436 dummyDocument->removeAllChildren(); 437 } 438 439 HTMLDocument* DummyDocumentFactory::s_sharedDummyDocument = 0; 440 int DummyDocumentFactory::s_sharedDummyDocumentMutex = 0; 441 398 442 HTMLTreeBuilder::FragmentParsingContext::FragmentParsingContext() 399 443 : m_fragment(0) … … 404 448 405 449 HTMLTreeBuilder::FragmentParsingContext::FragmentParsingContext(DocumentFragment* fragment, Element* contextElement, FragmentScriptingPermission scriptingPermission) 406 : m_dummyDocumentForFragmentParsing( HTMLDocument::create(0, KURL(), fragment->document()->baseURI()))450 : m_dummyDocumentForFragmentParsing(DummyDocumentFactory::createDummyDocument()) 407 451 , m_fragment(fragment) 408 452 , m_contextElement(contextElement) … … 410 454 { 411 455 m_dummyDocumentForFragmentParsing->setCompatibilityMode(fragment->document()->compatibilityMode()); 456 // Setting the baseURL should work the same as it would have had we passed 457 // it during HTMLDocument() construction, since the new document is empty. 458 m_dummyDocumentForFragmentParsing->setURL(fragment->document()->baseURI()); 412 459 } 413 460 … … 415 462 { 416 463 ASSERT(m_fragment); 417 return m_dummyDocumentForFragmentParsing .get();464 return m_dummyDocumentForFragmentParsing; 418 465 } 419 466 … … 421 468 { 422 469 // Populate the DocumentFragment with the parsed content now that we're done. 423 ContainerNode* root = m_dummyDocumentForFragmentParsing .get();470 ContainerNode* root = m_dummyDocumentForFragmentParsing; 424 471 if (m_contextElement) 425 472 root = m_dummyDocumentForFragmentParsing->documentElement(); 426 473 m_fragment->takeAllChildrenFrom(root); 474 ASSERT(!m_dummyDocumentForFragmentParsing->hasChildNodes()); 475 DummyDocumentFactory::releaseDocument(m_dummyDocumentForFragmentParsing); 476 m_dummyDocumentForFragmentParsing = 0; 427 477 } 428 478 -
trunk/Source/WebCore/html/parser/HTMLTreeBuilder.h
r76248 r77050 221 221 222 222 private: 223 RefPtr<Document> m_dummyDocumentForFragmentParsing; 223 // Use a shared dummy document to avoid expensive Document creation. 224 // Hold a raw pointer to the document since there is no need to ref it. 225 HTMLDocument* m_dummyDocumentForFragmentParsing; 224 226 DocumentFragment* m_fragment; 225 227 Element* m_contextElement;
Note: See TracChangeset
for help on using the changeset viewer.