Changeset 143498 in webkit


Ignore:
Timestamp:
Feb 20, 2013 1:43:29 PM (11 years ago)
Author:
fmalita@chromium.org
Message:

[SVG] Update of element referenced by multiple 'use' nodes is absurdly slow
https://bugs.webkit.org/show_bug.cgi?id=97905

Reviewed by Dirk Schulze.

Rebuilding the shadow and instance trees of dependent use nodes recursively can be
extremely inefficient with non-trivial dependency graphs (the trees are not constructed
in topological order).

To avoid redundant buildShadowAndInstanceTree() invokations, separate the invalidation
phase from the actual tree (re)building phase, and only descend into the dependency DAG
during the invalidation phase (recursion also stops at nodes that have been previously
invalidated).

No new tests: functional coverage provided by existing tests, perfomance tracked by
PerformanceTests/SVG/SvgNestedUse.html.

  • svg/SVGUseElement.cpp:

(WebCore::SVGUseElement::buildPendingResource):
(WebCore::SVGUseElement::buildShadowAndInstanceTree):
(WebCore::SVGUseElement::invalidateShadowTree):
(WebCore):
(WebCore::SVGUseElement::invalidateDependentShadowTrees):

  • svg/SVGUseElement.h:

(SVGUseElement):

Location:
trunk/Source/WebCore
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r143490 r143498  
     12013-02-20  Florin Malita  <fmalita@chromium.org>
     2
     3        [SVG] Update of element referenced by multiple 'use' nodes is absurdly slow
     4        https://bugs.webkit.org/show_bug.cgi?id=97905
     5
     6        Reviewed by Dirk Schulze.
     7
     8        Rebuilding the shadow and instance trees of dependent use nodes recursively can be
     9        extremely inefficient with non-trivial dependency graphs (the trees are not constructed
     10        in topological order).
     11
     12        To avoid redundant buildShadowAndInstanceTree() invokations, separate the invalidation
     13        phase from the actual tree (re)building phase, and only descend into the dependency DAG
     14        during the invalidation phase (recursion also stops at nodes that have been previously
     15        invalidated).
     16
     17        No new tests: functional coverage provided by existing tests, perfomance tracked by
     18        PerformanceTests/SVG/SvgNestedUse.html.
     19
     20        * svg/SVGUseElement.cpp:
     21        (WebCore::SVGUseElement::buildPendingResource):
     22        (WebCore::SVGUseElement::buildShadowAndInstanceTree):
     23        (WebCore::SVGUseElement::invalidateShadowTree):
     24        (WebCore):
     25        (WebCore::SVGUseElement::invalidateDependentShadowTrees):
     26        * svg/SVGUseElement.h:
     27        (SVGUseElement):
     28
    1292013-02-20  Tim Horton  <timothy_horton@apple.com>
    230
  • trunk/Source/WebCore/svg/SVGUseElement.cpp

    r143089 r143498  
    410410void SVGUseElement::buildPendingResource()
    411411{
    412     if (!referencedDocument())
     412    if (!referencedDocument() || isInShadowTree())
    413413        return;
    414414    clearResourceReferences();
    415     if (!inDocument() || isInShadowTree())
     415    if (!inDocument())
    416416        return;
    417417
     
    431431    }
    432432
    433     if (target->isSVGElement())
     433    if (target->isSVGElement()) {
    434434        buildShadowAndInstanceTree(static_cast<SVGElement*>(target));
     435        invalidateDependentShadowTrees();
     436    }
     437
    435438    ASSERT(!m_needsShadowTreeRecreation);
    436439}
     
    517520    // Update relative length information.
    518521    updateRelativeLengthsInformation();
    519 
    520     // Rebuild all dependent use elements.
    521     ASSERT(document());
    522     document()->accessSVGExtensions()->rebuildAllElementReferencesForTarget(this);
    523522
    524523    // Eventually dump instance tree
     
    907906    m_needsShadowTreeRecreation = true;
    908907    setNeedsStyleRecalc();
     908    invalidateDependentShadowTrees();
     909}
     910
     911void SVGUseElement::invalidateDependentShadowTrees()
     912{
     913    // Recursively invalidate dependent <use> shadow trees
     914    const HashSet<SVGElementInstance*>& instances = instancesForElement();
     915    const HashSet<SVGElementInstance*>::const_iterator end = instances.end();
     916    for (HashSet<SVGElementInstance*>::const_iterator it = instances.begin(); it != end; ++it) {
     917        if (SVGUseElement* element = (*it)->correspondingUseElement()) {
     918            ASSERT(element->inDocument());
     919            element->invalidateShadowTree();
     920        }
     921    }
    909922}
    910923
  • trunk/Source/WebCore/svg/SVGUseElement.h

    r141066 r143498  
    5151    SVGElementInstance* instanceForShadowTreeElement(Node*) const;
    5252    void invalidateShadowTree();
     53    void invalidateDependentShadowTrees();
    5354
    5455    RenderObject* rendererClipChild() const;
Note: See TracChangeset for help on using the changeset viewer.