WebKit Bugzilla
New
Browse
Log In
×
Sign in with GitHub
or
Remember my login
Create Account
·
Forgot Password
Forgotten password account recovery
RESOLVED FIXED
97905
[SVG] Update of element referenced by multiple 'use' nodes is absurdly slow
https://bugs.webkit.org/show_bug.cgi?id=97905
Summary
[SVG] Update of element referenced by multiple 'use' nodes is absurdly slow
Branimir Lambov
Reported
2012-09-28 06:30:53 PDT
Created
attachment 166239
[details]
Testcase The attached SVG animation contains an unit element that is used to draw a few hundred triangles by a hierarchy of 'use' nodes. The file animates the scale attribute of the unit element. This results in an update that takes tens of second for a single frame (i.e. on the order of 1/10 s for each triangle drawn!). Tested on Chrome Linux + MacOS and Safari MacOS, all have the problem. Opera runs this animation at 50 fps. Internet Explorer also does this smoothly.
Attachments
Testcase
(4.11 KB, image/svg+xml)
2012-09-28 06:30 PDT
,
Branimir Lambov
no flags
Details
Patch
(4.34 KB, patch)
2012-10-02 12:52 PDT
,
Florin Malita
no flags
Details
Formatted Diff
Diff
Patch for landing
(4.31 KB, patch)
2013-02-20 13:03 PST
,
Florin Malita
no flags
Details
Formatted Diff
Diff
Show Obsolete
(1)
View All
Add attachment
proposed patch, testcase, etc.
Branimir Lambov
Comment 1
2012-09-28 07:19:25 PDT
Additionally, if you leave the 'qqqqq' definition unused (e.g. by changing line 51 to refer to '#qqq' instead), the file's performance will not improve.
Florin Malita
Comment 2
2012-09-28 10:32:44 PDT
This has the same profile as
https://bugs.webkit.org/show_bug.cgi?id=97910
, so I suspect it's the same problem: + 3.81% SignalSender libpthread-2.15.so [.] pthread_mutex_lock + 3.65% SignalSender libpthread-2.15.so [.] pthread_mutex_unlock + 1.79% SignalSender libwebkit.so [.] WTF::StringHasher::addCharactersToHash(unsigned short, unsigned short) + 1.49% SignalSender libwebkit.so [.] WTF::Locker<WTF::Mutex>::Locker(WTF::Mutex&) + 1.39% SignalSender libwebkit.so [.] WTF::intHash(unsigned long) + 1.34% SignalSender libwebkit.so [.] WTF::OwnPtr<WTF::Mutex>::operator*() const + 1.03% SignalSender libwebkit.so [.] WebCore::Node::getFlag(WebCore::Node::NodeFlags) const + 1.01% SignalSender libwebkit.so [.] WTF::Mutex::lock() + 0.92% SignalSender libpthread-2.15.so [.] pthread_getspecific + 0.92% SignalSender libwebkit.so [.] WTF::ThreadRestrictionVerifier::isSafeToUse() const + 0.81% SignalSender libwebkit.so [.] unsigned int WTF::StringHasher::computeHashAndMaskTop8Bits<unsigned short, &(WTF::StringHasher::defaultConverter(unsigned short))>( + 0.78% SignalSender chrome [.] (anonymous namespace)::FL_Previous_No_Check(void*) + 0.69% SignalSender chrome [.] PackedCache<36, unsigned long>::GetOrDefault(unsigned long, unsigned long) const + 0.68% SignalSender libwebkit.so [.] WTF::RefPtr<WTF::StringImpl>::get() const + 0.67% SignalSender libwebkit.so [.] WTF::currentThread() + 0.61% SignalSender libwebkit.so [.] WTF::Mutex::unlock() + 0.58% SignalSender chrome [.] base::subtle::Acquire_Load(long const volatile*) + 0.57% SignalSender libwebkit.so [.] WTF::ThreadIdentifierData::identifier() + 0.56% SignalSender libwebkit.so [.] WTF::StringHasher::defaultConverter(unsigned short) + 0.56% SignalSender libwebkit.so [.] WebCore::Node::document() const + 0.55% SignalSender chrome [.] TCMalloc_PageMap3<36>::get(unsigned long) const + 0.55% SignalSender libwebkit.so [.] WTF::RefCountedBase::derefBase() + 0.53% SignalSender libwebkit.so [.] WTF::RefCountedBase::ref() + 0.53% SignalSender libwebkit.so [.] WTF::Locker<WTF::Mutex>::~Locker()
Florin Malita
Comment 3
2012-09-28 11:03:36 PDT
There are all kinds of nasty going on here, we're rebuilding the shadow and instance trees waaaay more times than we should.
Nikolas Zimmermann
Comment 4
2012-10-01 01:11:20 PDT
(In reply to
comment #3
)
> There are all kinds of nasty going on here, we're rebuilding the shadow and instance trees waaaay more times than we should.
<g id="unit"> <polygon points="0,0 10,0 5,8.66025403784439"/> </g> unit.setAttribute('transform', 'scale(' + (Math.abs(f%20-10)/10) + ')'); This causes all instance & shadow trees of all the <use> elements referencing "unit" to be rebuilt. If this would use <animateTransform> exactly this kind of cloning is suppressed. An SVGAnimateTransformElement knows how to update all instances without having to rebuild/reclone. Unfortunately I have zero time at the moment for large patches, what we really want to assure: - Only rebuild shadow/dom trees if the DOM is mutated by insertions or removal. - Never rebuild the trees for attribute changes, we can always find all instances of a cloned element and propagate updates to them for both XML DOM (setAttribute) and SVG DOM (foo.x.baseVal.value=..) changes. This would fix the root of these problems.
Florin Malita
Comment 5
2012-10-01 05:59:13 PDT
(In reply to
comment #4
)
> - Only rebuild shadow/dom trees if the DOM is mutated by insertions or removal. > - Never rebuild the trees for attribute changes, we can always find all instances of a cloned element and propagate updates to them for both XML DOM (setAttribute) and SVG DOM (foo.x.baseVal.value=..) changes. > > This would fix the root of these problems.
Agreed, these are good ideas Niko and they should greatly improve use performance. In this bug/example, there's a particularly bad interaction going on on top of the expensive tree rebuild: rebuilding dependent use trees is recursive, causing many unnecessary updates that just get thrown away. Say we have L groups containing N use elements each, and each use in L depends on all other uses in L-1 (in the example L = 5 and N = 4), and all uses in group0 depend on some element. If the element is updated, we start rebuilding use0 in group0 and then we're immediately rebuilding all dependent uses in group1 (which propagates recursively all the way). Then we move on to use1, and again invalidate and rebuild all the uses in group1 and so on. That introduces a N^L factor for this kind of setup because we're not rebuilding the trees in topological (sorted use-dependency) order. I believe this should not be too hard to address if we have a separate (recursive) invalidation phase and a non-recursive rebuild phase. I'm playing with it right now, hope to have something working in the next days.
Florin Malita
Comment 6
2012-10-02 12:52:50 PDT
Created
attachment 166736
[details]
Patch
Florin Malita
Comment 7
2012-10-02 13:02:14 PDT
The patch doesn't address the general slowness of <use> shadow/instance tree rebuilds (will focus on that in
https://bugs.webkit.org/show_bug.cgi?id=97910
), but it removes many redundant updates triggered by this test (on my workstation it increases the framerate from ~0.04fps to ~9.5fps).
Dirk Schulze
Comment 8
2013-02-15 23:45:27 PST
Comment on
attachment 166736
[details]
Patch Sounds reasonable. Not sure if it still applies so. r=me.
Florin Malita
Comment 9
2013-02-20 13:01:29 PST
(In reply to
comment #8
)
> (From update of
attachment 166736
[details]
) > Sounds reasonable. Not sure if it still applies so. r=me.
Yes, this is still relevant. Thanks!
Florin Malita
Comment 10
2013-02-20 13:03:15 PST
Created
attachment 189361
[details]
Patch for landing
Dirk Schulze
Comment 11
2013-02-20 13:25:04 PST
(In reply to
comment #9
)
> (In reply to
comment #8
) > > (From update of
attachment 166736
[details]
[details]) > > Sounds reasonable. Not sure if it still applies so. r=me. > > Yes, this is still relevant. Thanks!
If the patch still applies to ToT. :)
WebKit Review Bot
Comment 12
2013-02-20 13:45:12 PST
Comment on
attachment 189361
[details]
Patch for landing Clearing flags on attachment: 189361 Committed
r143498
: <
http://trac.webkit.org/changeset/143498
>
WebKit Review Bot
Comment 13
2013-02-20 13:45:15 PST
All reviewed patches have been landed. Closing bug.
Note
You need to
log in
before you can comment on or make changes to this bug.
Top of Page
Format For Printing
XML
Clone This Bug