Created attachment 166245 [details] Example setting href attribute The attached files contain a hierarchy of 'use' elements to build a graphic containing a few hundred triangles. It is not a problem for Chrome to render the graphic fluidly (use-levels-move), but if a new 'use' element references the graphic (use-levels-new-use), or the element's 'href' is changed (use-levels-set-href), the performance falls dramatically. WebKit is copying the elements referenced by 'use', which should not be necessary at all. In other tests we have seen that it is actually faster to explicitly recreate referenced nodes with JavaScript than to refer to them with 'use' elements. Opera does not have this problem, and runs all these examples at ~50 fps.
Created attachment 166246 [details] Example creating new 'use' element
Created attachment 166247 [details] Example without changing reference, demonstrating what the performance should be
(In reply to comment #0) > WebKit is copying the elements referenced by 'use', which should not be necessary at all. Deep cloning is likely needed to support full <use> semantics - see http://www.w3.org/TR/SVG/struct.html#UseElement But the profile for the slow tests does seem odd - most cycles wasted in synchronization and string manipulation code: 2.77% chrome libpthread-2.15.so [.] pthread_mutex_unlock 2.59% chrome libpthread-2.15.so [.] pthread_mutex_lock 1.36% swapper [kernel.kallsyms] [k] mwait_idle_with_hints 1.35% chrome libwebkit.so [.] WTF::StringHasher::addCharactersToHash(unsigned short, unsigned short) 1.25% chrome libwebkit.so [.] WTF::intHash(unsigned long) 1.10% chrome libwebkit.so [.] WTF::OwnPtr<WTF::Mutex>::operator*() const 1.05% chrome libwebkit.so [.] WTF::Locker<WTF::Mutex>::Locker(WTF::Mutex&) 0.96% chrome libwebkit.so [.] WTF::Mutex::lock() 0.94% chrome libwebkit.so [.] WebCore::Node::getFlag(WebCore::Node::NodeFlags) const 0.79% chrome libwebkit.so [.] WTF::ThreadRestrictionVerifier::isSafeToUse() const 0.76% chrome libwebkit.so [.] WTF::RefPtr<WTF::StringImpl>::get() const 0.73% chrome chrome [.] (anonymous namespace)::FL_Previous_No_Check(void*) 0.71% chrome libwebkit.so [.] unsigned int WTF::StringHasher::computeHashAndMaskTop8Bits<unsigned short, &(WTF::StringHasher::defaultConverter(unsi 0.63% chrome libpthread-2.15.so [.] pthread_getspecific 0.58% chrome chrome [.] PackedCache<36, unsigned long>::GetOrDefault(unsigned long, unsigned long) const 0.57% chrome libwebkit.so [.] WebCore::Node::document() const 0.50% chrome chrome [.] TCMalloc_PageMap3<36>::get(unsigned long) const 0.50% chrome libwebkit.so [.] bool WTF::IdentityHashTranslator<WTF::PtrHash<WebCore::SVGElement*> >::equal<WebCore::SVGElement*>(WebCore::SVGElemen 0.48% chrome libwebkit.so [.] WTF::Mutex::unlock() 0.47% cinnamon [kernel.kallsyms] [k] audit_filter_syscall 0.46% chrome libwebkit.so [.] WTF::ThreadIdentifierData::identifier() 0.44% chrome libc-2.15.so [.] __memset_sse2 0.44% chrome chrome [.] base::subtle::Acquire_Load(long const volatile*) 0.44% chrome chrome (deleted) [.] 0x3255b0f 0.39% chrome libwebkit.so [.] WTF::String::impl() const 0.38% chrome libwebkit.so [.] WTF::Locker<WTF::Mutex>::~Locker() 0.37% chrome libwebkit.so [.] void WTF::addIterator<WebCore::SVGElement*, WTF::KeyValuePair<WebCore::SVGElement*, WTF::OwnPtr<WTF::HashSet<WebCore: 0.37% chrome libwebkit.so [.] WTF::RefCountedBase::derefBase() 0.35% chrome chrome [.] CheckCachedSizeClass(void*) 0.32% chrome libwebkit.so [.] WebCore::RenderObject::document() const 0.32% chrome chrome [.] (anonymous namespace)::MaskPtr(void*) 0.32% chrome libwebkit.so [.] WTF::StringHasher::defaultConverter(unsigned short) 0.31% chrome libwebkit.so [.] WTF::doubleHash(unsigned int) 0.31% chrome libwebkit.so [.] WTF::RefCountedBase::ref() 0.28% chrome libwebkit.so [.] void WTF::removeIterator<WebCore::SVGElement*, WTF::KeyValuePair<WebCore::SVGElement*, WTF::OwnPtr<WTF::HashSet<WebCo 0.27% chrome libwebkit.so [.] WTF::currentThread() 0.27% chrome libwebkit.so [.] WTF::StringHasher::avalancheBits() const
See 97905 comment #4 for a way out of this mess.