Changeset 136334 in webkit


Ignore:
Timestamp:
Dec 2, 2012 4:03:44 AM (11 years ago)
Author:
akling@apple.com
Message:

Keep ElementAttributeData sharing cache open for a while after document parsing finishes.
<http://webkit.org/b/103720>

Reviewed by Antti Koivisto.

Allow web pages that generate content dynamically to benefit more from the ElementAttributeData sharing
cache by keeping it open for 10 seconds after document parsing finishes. This enables elements constructed
from HTML fragments to share attribute data with other identical elements.

Elements created via Document.createElement are still unsupported since we don't know the list of attributes
at the time of construction.

401kB progression on Membuster3.

Document now holds on to a DocumentSharedObjectPool, accessible via Document::sharedObjectPool().
It is non-null during parsing and for some time afterwards, and can be used to implement additional
caches that are not worth holding on to permanently.

  • CMakeLists.txt:
  • GNUmakefile.list.am:
  • Target.pri:
  • WebCore.gypi:
  • WebCore.xcodeproj/project.pbxproj:
  • WebCore.vcproj/WebCore.vcproj:

Add new class DocumentSharedObjectPool.

  • dom/Document.cpp:

(WebCore::Document::Document):
(WebCore::Document::setParsing):
(WebCore::Document::finishedParsing):
(WebCore::Document::sharedObjectPoolClearTimerFired):

  • dom/Document.h:

(WebCore::Document::sharedObjectPool):

Create DocumentSharedObjectPool when parsing starts, kill it on a 10s timer after parsing finishes.

  • dom/DocumentSharedObjectPool.cpp: Added.

(ImmutableElementAttributeDataCacheKey):
(WebCore::ImmutableElementAttributeDataCacheKey::ImmutableElementAttributeDataCacheKey):
(WebCore::ImmutableElementAttributeDataCacheKey::operator!=):
(WebCore::ImmutableElementAttributeDataCacheKey::hash):
(ImmutableElementAttributeDataCacheEntry):
(WebCore::ImmutableElementAttributeDataCacheEntry::ImmutableElementAttributeDataCacheEntry):
(WebCore::DocumentSharedObjectPool::cachedImmutableElementAttributeData):
(WebCore::DocumentSharedObjectPool::DocumentSharedObjectPool):
(WebCore::DocumentSharedObjectPool::~DocumentSharedObjectPool):

  • dom/DocumentSharedObjectPool.h: Added.

(DocumentSharedObjectPool):
(WebCore::DocumentSharedObjectPool::create):

  • dom/Element.cpp:

(WebCore::Element::parserSetAttributes):

Moved the ElementAttributeData cache to DocumentSharedObjectPool.

Location:
trunk/Source/WebCore
Files:
2 added
11 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/CMakeLists.txt

    r136205 r136334  
    11461146    dom/DocumentParser.cpp
    11471147    dom/DocumentOrderedMap.cpp
     1148    dom/DocumentSharedObjectPool.cpp
    11481149    dom/DocumentStyleSheetCollection.cpp
    11491150    dom/DocumentType.cpp
  • trunk/Source/WebCore/ChangeLog

    r136332 r136334  
     12012-12-02  Andreas Kling  <akling@apple.com>
     2
     3        Keep ElementAttributeData sharing cache open for a while after document parsing finishes.
     4        <http://webkit.org/b/103720>
     5
     6        Reviewed by Antti Koivisto.
     7
     8        Allow web pages that generate content dynamically to benefit more from the ElementAttributeData sharing
     9        cache by keeping it open for 10 seconds after document parsing finishes. This enables elements constructed
     10        from HTML fragments to share attribute data with other identical elements.
     11
     12        Elements created via Document.createElement are still unsupported since we don't know the list of attributes
     13        at the time of construction.
     14
     15        401kB progression on Membuster3.
     16
     17        Document now holds on to a DocumentSharedObjectPool, accessible via Document::sharedObjectPool().
     18        It is non-null during parsing and for some time afterwards, and can be used to implement additional
     19        caches that are not worth holding on to permanently.
     20
     21        * CMakeLists.txt:
     22        * GNUmakefile.list.am:
     23        * Target.pri:
     24        * WebCore.gypi:
     25        * WebCore.xcodeproj/project.pbxproj:
     26        * WebCore.vcproj/WebCore.vcproj:
     27
     28            Add new class DocumentSharedObjectPool.
     29
     30        * dom/Document.cpp:
     31        (WebCore::Document::Document):
     32        (WebCore::Document::setParsing):
     33        (WebCore::Document::finishedParsing):
     34        (WebCore::Document::sharedObjectPoolClearTimerFired):
     35        * dom/Document.h:
     36        (WebCore::Document::sharedObjectPool):
     37
     38            Create DocumentSharedObjectPool when parsing starts, kill it on a 10s timer after parsing finishes.
     39
     40        * dom/DocumentSharedObjectPool.cpp: Added.
     41        (ImmutableElementAttributeDataCacheKey):
     42        (WebCore::ImmutableElementAttributeDataCacheKey::ImmutableElementAttributeDataCacheKey):
     43        (WebCore::ImmutableElementAttributeDataCacheKey::operator!=):
     44        (WebCore::ImmutableElementAttributeDataCacheKey::hash):
     45        (ImmutableElementAttributeDataCacheEntry):
     46        (WebCore::ImmutableElementAttributeDataCacheEntry::ImmutableElementAttributeDataCacheEntry):
     47        (WebCore::DocumentSharedObjectPool::cachedImmutableElementAttributeData):
     48        (WebCore::DocumentSharedObjectPool::DocumentSharedObjectPool):
     49        (WebCore::DocumentSharedObjectPool::~DocumentSharedObjectPool):
     50        * dom/DocumentSharedObjectPool.h: Added.
     51        (DocumentSharedObjectPool):
     52        (WebCore::DocumentSharedObjectPool::create):
     53        * dom/Element.cpp:
     54        (WebCore::Element::parserSetAttributes):
     55
     56            Moved the ElementAttributeData cache to DocumentSharedObjectPool.
     57
    1582012-12-02  John Bauman  <jbauman@chromium.org>
    259
  • trunk/Source/WebCore/GNUmakefile.list.am

    r136205 r136334  
    27582758        Source/WebCore/dom/DocumentParser.cpp \
    27592759        Source/WebCore/dom/DocumentParser.h \
     2760        Source/WebCore/dom/DocumentSharedObjectPool.cpp \
     2761        Source/WebCore/dom/DocumentSharedObjectPool.h \
    27602762    Source/WebCore/dom/DocumentStyleSheetCollection.cpp \
    27612763    Source/WebCore/dom/DocumentStyleSheetCollection.h \
  • trunk/Source/WebCore/Target.pri

    r136235 r136334  
    376376    dom/DocumentOrderedMap.cpp \
    377377    dom/DocumentParser.cpp \
     378    dom/DocumentSharedObjectPool.cpp \
    378379    dom/DocumentStyleSheetCollection.cpp \
    379380    dom/DocumentType.cpp \
     
    15571558    dom/DocumentMarkerController.h \
    15581559    dom/DocumentOrderedMap.h \
     1560    dom/DocumentSharedObjectPool.h \
    15591561    dom/DocumentStyleSheetCollection.h \
    15601562    dom/DocumentType.h \
  • trunk/Source/WebCore/WebCore.gypi

    r136319 r136334  
    660660            'dom/DocumentOrderedMap.h',
    661661            'dom/DocumentParser.h',
     662            'dom/DocumentSharedObjectPool.h',
    662663            'dom/DocumentStyleSheetCollection.h',
    663664            'dom/DocumentTiming.h',
     
    38073808            'dom/DocumentOrderedMap.cpp',
    38083809            'dom/DocumentParser.cpp',
     3810            'dom/DocumentSharedObjectPool.cpp',
    38093811            'dom/DocumentStyleSheetCollection.cpp',
    38103812            'dom/DocumentType.cpp',
  • trunk/Source/WebCore/WebCore.vcproj/WebCore.vcproj

    r136205 r136334  
    5067550675                        </File>
    5067650676                        <File
     50677                                RelativePath="..\dom\DocumentSharedObjectPool.cpp"
     50678                                >
     50679                        </File>
     50680                        <File
     50681                                RelativePath="..\dom\DocumentSharedObjectPool.h"
     50682                                >
     50683                        </File>
     50684                        <File
    5067750685                                RelativePath="..\dom\DocumentStyleSheetCollection.cpp"
    5067850686                                >
  • trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj

    r136211 r136334  
    46274627                AD4495F3141FC08900541EDF /* EventListenerMap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AD4495F1141FC08900541EDF /* EventListenerMap.cpp */; };
    46284628                AD4495F4141FC08900541EDF /* EventListenerMap.h in Headers */ = {isa = PBXBuildFile; fileRef = AD4495F2141FC08900541EDF /* EventListenerMap.h */; settings = {ATTRIBUTES = (Private, ); }; };
     4629                AD6E71AC1668899D00320C13 /* DocumentSharedObjectPool.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AD6E71AA1668899D00320C13 /* DocumentSharedObjectPool.cpp */; };
     4630                AD6E71AD1668899D00320C13 /* DocumentSharedObjectPool.h in Headers */ = {isa = PBXBuildFile; fileRef = AD6E71AB1668899D00320C13 /* DocumentSharedObjectPool.h */; };
    46294631                ADDF1AD71257CD9A0003A759 /* RenderSVGPath.h in Headers */ = {isa = PBXBuildFile; fileRef = ADDF1AD51257CD9A0003A759 /* RenderSVGPath.h */; };
    46304632                B10B6980140C174000BC1C26 /* WebVTTToken.h in Headers */ = {isa = PBXBuildFile; fileRef = B10B697D140C174000BC1C26 /* WebVTTToken.h */; };
     
    1184611848                AD4495F1141FC08900541EDF /* EventListenerMap.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = EventListenerMap.cpp; sourceTree = "<group>"; };
    1184711849                AD4495F2141FC08900541EDF /* EventListenerMap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EventListenerMap.h; sourceTree = "<group>"; };
     11850                AD6E71AA1668899D00320C13 /* DocumentSharedObjectPool.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DocumentSharedObjectPool.cpp; sourceTree = "<group>"; };
     11851                AD6E71AB1668899D00320C13 /* DocumentSharedObjectPool.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DocumentSharedObjectPool.h; sourceTree = "<group>"; };
    1184811852                ADDF1AD41257CD9A0003A759 /* RenderSVGPath.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RenderSVGPath.cpp; sourceTree = "<group>"; };
    1184911853                ADDF1AD51257CD9A0003A759 /* RenderSVGPath.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RenderSVGPath.h; sourceTree = "<group>"; };
     
    2219522199                                4123E568127B3041000FEEA7 /* WindowEventContext.cpp */,
    2219622200                                4123E567127B3041000FEEA7 /* WindowEventContext.h */,
     22201                                AD6E71AA1668899D00320C13 /* DocumentSharedObjectPool.cpp */,
     22202                                AD6E71AB1668899D00320C13 /* DocumentSharedObjectPool.h */,
    2219722203                        );
    2219822204                        path = dom;
     
    2585225858                                447958041643B49A001E0A7F /* ParsedContentType.h in Headers */,
    2585325859                                FB2C15C3165D649D0039C9F8 /* CachedSVGDocumentReference.h in Headers */,
     25860                                AD6E71AD1668899D00320C13 /* DocumentSharedObjectPool.h in Headers */,
    2585425861                                31741AAD16636609008A5B7E /* SimulatedClickOptions.h in Headers */,
    2585525862                                15B8B7C91652C5220036EF55 /* JSWebKitCSSMixFunctionValue.h in Headers */,
     
    2895528962                                1E50084816516AD800B7E098 /* RenderThemeMacShared.mm in Sources */,
    2895628963                                CD7E05221651C28200C1201F /* WebCoreAVFResourceLoader.mm in Sources */,
     28964                                AD6E71AC1668899D00320C13 /* DocumentSharedObjectPool.cpp in Sources */,
    2895728965                                447958051643B4B2001E0A7F /* ParsedContentType.cpp in Sources */,
    2895828966                                15B8B7C81652C5220036EF55 /* JSWebKitCSSMixFunctionValue.cpp in Sources */,
  • trunk/Source/WebCore/dom/DOMAllInOne.cpp

    r135671 r136334  
    6767#include "DocumentOrderedMap.cpp"
    6868#include "DocumentParser.cpp"
     69#include "DocumentSharedObjectPool.cpp"
    6970#include "DocumentType.cpp"
    7071#include "Element.cpp"
  • trunk/Source/WebCore/dom/Document.cpp

    r136277 r136334  
    5656#include "DocumentLoader.h"
    5757#include "DocumentMarkerController.h"
     58#include "DocumentSharedObjectPool.h"
    5859#include "DocumentStyleSheetCollection.h"
    5960#include "DocumentType.h"
     
    501502    , m_visualUpdatesAllowed(true)
    502503    , m_visualUpdatesSuppressionTimer(this, &Document::visualUpdatesSuppressionTimerFired)
     504    , m_sharedObjectPoolClearTimer(this, &Document::sharedObjectPoolClearTimerFired)
    503505#ifndef NDEBUG
    504506    , m_didDispatchViewportPropertiesChanged(false)
     
    24922494{
    24932495    m_bParsing = b;
     2496
     2497    if (m_bParsing && !m_sharedObjectPool)
     2498        m_sharedObjectPool = DocumentSharedObjectPool::create();
     2499
    24942500    if (!m_bParsing && view())
    24952501        view()->scheduleRelayout();
     
    44164422    }
    44174423
    4418     // The ElementAttributeData sharing cache is only used during parsing since
    4419     // that's when the majority of immutable attribute data will be created.
    4420     m_immutableAttributeDataCache.clear();
     4424    // Schedule dropping of the DocumentSharedObjectPool. We keep it alive for a while after parsing finishes
     4425    // so that dynamically inserted content can also benefit from sharing optimizations.
     4426    // Note that we don't refresh the timer on pool access since that could lead to huge caches being kept
     4427    // alive indefinitely by something innocuous like JS setting .innerHTML repeatedly on a timer.
     4428    static const int timeToKeepSharedObjectPoolAliveAfterParsingFinishedInSeconds = 10;
     4429    m_sharedObjectPoolClearTimer.startOneShot(timeToKeepSharedObjectPoolAliveAfterParsingFinishedInSeconds);
     4430}
     4431
     4432void Document::sharedObjectPoolClearTimerFired(Timer<Document>*)
     4433{
     4434    m_sharedObjectPool.clear();
    44214435}
    44224436
     
    58615875}
    58625876
    5863 class ImmutableAttributeDataCacheKey {
    5864 public:
    5865     ImmutableAttributeDataCacheKey(const Attribute* attributes, unsigned attributeCount)
    5866         : m_attributes(attributes)
    5867         , m_attributeCount(attributeCount)
    5868     { }
    5869 
    5870     bool operator!=(const ImmutableAttributeDataCacheKey& other) const
    5871     {
    5872         if (m_attributeCount != other.m_attributeCount)
    5873             return true;
    5874         return memcmp(m_attributes, other.m_attributes, sizeof(Attribute) * m_attributeCount);
    5875     }
    5876 
    5877     unsigned hash() const
    5878     {
    5879         return StringHasher::hashMemory(m_attributes, m_attributeCount * sizeof(Attribute));
    5880     }
    5881 
    5882 private:
    5883     const Attribute* m_attributes;
    5884     unsigned m_attributeCount;
    5885 };
    5886 
    5887 struct ImmutableAttributeDataCacheEntry {
    5888     ImmutableAttributeDataCacheEntry(const ImmutableAttributeDataCacheKey& k, PassRefPtr<ElementAttributeData> v)
    5889         : key(k)
    5890         , value(v)
    5891     { }
    5892 
    5893     ImmutableAttributeDataCacheKey key;
    5894     RefPtr<ElementAttributeData> value;
    5895 };
    5896 
    5897 PassRefPtr<ElementAttributeData> Document::cachedImmutableAttributeData(const Vector<Attribute>& attributes)
    5898 {
    5899     ASSERT(!attributes.isEmpty());
    5900 
    5901     ImmutableAttributeDataCacheKey cacheKey(attributes.data(), attributes.size());
    5902     unsigned cacheHash = cacheKey.hash();
    5903 
    5904     ImmutableAttributeDataCache::iterator cacheIterator = m_immutableAttributeDataCache.add(cacheHash, nullptr).iterator;
    5905     if (cacheIterator->value && cacheIterator->value->key != cacheKey)
    5906         cacheHash = 0;
    5907 
    5908     RefPtr<ElementAttributeData> attributeData;
    5909     if (cacheHash && cacheIterator->value)
    5910         attributeData = cacheIterator->value->value;
    5911     else
    5912         attributeData = ElementAttributeData::createImmutable(attributes);
    5913 
    5914     if (!cacheHash || cacheIterator->value)
    5915         return attributeData.release();
    5916 
    5917     cacheIterator->value = adoptPtr(new ImmutableAttributeDataCacheEntry(ImmutableAttributeDataCacheKey(attributeData->immutableAttributeArray(), attributeData->length()), attributeData));
    5918 
    5919     return attributeData.release();
    5920 }
    5921 
    59225877bool Document::haveStylesheetsLoaded() const
    59235878{
  • trunk/Source/WebCore/dom/Document.h

    r136328 r136334  
    7878class DocumentMarkerController;
    7979class DocumentParser;
     80class DocumentSharedObjectPool;
    8081class DocumentStyleSheetCollection;
    8182class DocumentType;
    8283class DocumentWeakReference;
    8384class Element;
    84 class ElementAttributeData;
    8585class EntityReference;
    8686class Event;
     
    207207const int numNodeListInvalidationTypes = InvalidateOnAnyAttrChange + 1;
    208208
    209 struct ImmutableAttributeDataCacheEntry;
    210 typedef HashMap<unsigned, OwnPtr<ImmutableAttributeDataCacheEntry>, AlreadyHashed> ImmutableAttributeDataCache;
    211 
    212209class Document : public ContainerNode, public TreeScope, public ScriptExecutionContext {
    213210public:
     
    11541151    virtual void reportMemoryUsage(MemoryObjectInfo*) const OVERRIDE;
    11551152
    1156     PassRefPtr<ElementAttributeData> cachedImmutableAttributeData(const Vector<Attribute>&);
     1153    DocumentSharedObjectPool* sharedObjectPool() { return m_sharedObjectPool.get(); }
    11571154
    11581155    void didRemoveAllPendingStylesheet();
     
    15161513#endif
    15171514
    1518     ImmutableAttributeDataCache m_immutableAttributeDataCache;
     1515    void sharedObjectPoolClearTimerFired(Timer<Document>*);
     1516    Timer<Document> m_sharedObjectPoolClearTimer;
     1517
     1518    OwnPtr<DocumentSharedObjectPool> m_sharedObjectPool;
    15191519
    15201520#ifndef NDEBUG
  • trunk/Source/WebCore/dom/Element.cpp

    r136331 r136334  
    3838#include "Document.h"
    3939#include "DocumentFragment.h"
     40#include "DocumentSharedObjectPool.h"
    4041#include "ElementRareData.h"
    4142#include "ExceptionCode.h"
     
    977978    }
    978979
    979     // When the document is in parsing state, we cache immutable ElementAttributeData objects with the
    980     // input attribute vector as key. (This cache is held by Document.)
    981     if (!document() || !document()->parsing())
     980    if (document() && document()->sharedObjectPool())
     981        m_attributeData = document()->sharedObjectPool()->cachedImmutableElementAttributeData(filteredAttributes);
     982    else
    982983        m_attributeData = ElementAttributeData::createImmutable(filteredAttributes);
    983     else
    984         m_attributeData = document()->cachedImmutableAttributeData(filteredAttributes);
    985984
    986985    // Iterate over the set of attributes we already have on the stack in case
Note: See TracChangeset for help on using the changeset viewer.