NEW 208780
No need to schedule/unschedule style recalcs and layouts inside of a rendering update
https://bugs.webkit.org/show_bug.cgi?id=208780
Summary No need to schedule/unschedule style recalcs and layouts inside of a renderin...
Simon Fraser (smfr)
Reported 2020-03-07 18:15:40 PST
We waste time updating timers during a rendering update: Style recalc timer: CFRunLoopTimerSetNextFireDate WebCore::MainThreadSharedTimer::setFireInterval(WTF::Seconds) WebCore::ThreadTimers::updateSharedTimer() WebCore::TimerBase::setNextFireTime(WTF::MonotonicTime) WebCore::TimerBase::start(WTF::Seconds, WTF::Seconds) WebCore::TimerBase::startOneShot(WTF::Seconds) WebCore::Document::scheduleStyleRecalc() WebCore::Node::updateAncestorsForStyleRecalc() WebCore::Node::invalidateStyle(WebCore::Style::Validity, WebCore::Style::InvalidationMode) WebCore::Element::invalidateStyle() WebCore::StyledElement::invalidateStyleAttribute() WebCore::InlineCSSStyleDeclaration::didMutate(WebCore::PropertySetCSSStyleDeclaration::MutationType) WebCore::PropertySetCSSStyleDeclaration::setPropertyInternal(WebCore::CSSPropertyID, WTF::String const&, bool) WebCore::CSSStyleDeclaration::setNamedItem(WTF::AtomString const&, WTF::String, bool&) WebCore::JSCSSStyleDeclaration::put(JSC::JSCell*, JSC::JSGlobalObject*, JSC::PropertyName, JSC::JSValue, JSC::PutPropertySlot&) JSC::JSCell::putInline(JSC::JSGlobalObject*, JSC::PropertyName, JSC::JSValue, JSC::PutPropertySlot&) JSC::JSValue::putInline(JSC::JSGlobalObject*, JSC::PropertyName, JSC::JSValue, JSC::PutPropertySlot&) operationPutByIdNonStrict 0x4ed07c0002cd vmEntryToJavaScript JSC::JITCode::execute(JSC::VM*, JSC::ProtoCallFrame*) JSC::Interpreter::executeCall(JSC::JSGlobalObject*, JSC::JSObject*, JSC::CallType, JSC::CallData const&, JSC::JSValue, JSC::ArgList const&) JSC::call(JSC::JSGlobalObject*, JSC::JSValue, JSC::CallType, JSC::CallData const&, JSC::JSValue, JSC::ArgList const&) JSC::call(JSC::JSGlobalObject*, JSC::JSValue, JSC::CallType, JSC::CallData const&, JSC::JSValue, JSC::ArgList const&, WTF::NakedPtr<JSC::Exception>&) JSC::profiledCall(JSC::JSGlobalObject*, JSC::ProfilingReason, JSC::JSValue, JSC::CallType, JSC::CallData const&, JSC::JSValue, JSC::ArgList const&, WTF::NakedPtr<JSC::Exception>&) WebCore::JSExecState::profiledCall(JSC::JSGlobalObject*, JSC::ProfilingReason, JSC::JSValue, JSC::CallType, JSC::CallData const&, JSC::JSValue, JSC::ArgList const&, WTF::NakedPtr<JSC::Exception>&) WebCore::JSEventListener::handleEvent(WebCore::ScriptExecutionContext&, WebCore::Event&) WebCore::EventTarget::innerInvokeEventListeners(WebCore::Event&, WTF::Vector<WTF::RefPtr<WebCore::RegisteredEventListener, WTF::DumbPtrTraits<WebCore::RegisteredEventListener> >, 1ul, WTF::CrashOnOverflow, 16ul, WTF::FastMalloc>, WebCore::EventTarget::EventInvokePhase) WebCore::EventTarget::fireEventListeners(WebCore::Event&, WebCore::EventTarget::EventInvokePhase) WebCore::WindowEventContext::handleLocalEvents(WebCore::Event&, WebCore::EventTarget::EventInvokePhase) const WebCore::dispatchEventInDOM(WebCore::Event&, WebCore::EventPath const&) WebCore::EventDispatcher::dispatchEvent(WebCore::Node&, WebCore::Event&) WebCore::Node::dispatchEvent(WebCore::Event&) WebCore::Document::runScrollSteps() WebCore::Page::updateRendering()::$_13::operator()(WebCore::Document&) const CFRunLoopTimerSetNextFireDate WebCore::MainThreadSharedTimer::setFireInterval(WTF::Seconds) WebCore::ThreadTimers::updateSharedTimer() WebCore::TimerBase::setNextFireTime(WTF::MonotonicTime) WebCore::TimerBase::stop() WebCore::Document::unscheduleStyleRecalc() WebCore::Document::resolveStyle(WebCore::Document::ResolveStyleType) WebCore::Document::updateStyleIfNeeded() WebCore::FrameView::updateLayoutAndStyleIfNeededRecursive() WebCore::Page::layoutIfNeeded() WebCore::Page::updateRendering() WebKit::WebPage::updateRendering() Layout timer: WebCore::MainThreadSharedTimer::setFireInterval(WTF::Seconds) WebCore::ThreadTimers::updateSharedTimer() WebCore::TimerBase::setNextFireTime(WTF::MonotonicTime) WebCore::TimerBase::start(WTF::Seconds, WTF::Seconds) WebCore::TimerBase::startOneShot(WTF::Seconds) WebCore::FrameViewLayoutContext::scheduleLayout() WebCore::scheduleRelayoutForSubtree(WebCore::RenderElement&) WebCore::RenderObject::markContainingBlocksForLayout(WebCore::ScheduleRelayout, WebCore::RenderElement*) WebCore::RenderElement::setNeedsPositionedMovementLayout(WebCore::RenderStyle const*) WebCore::RenderElement::styleDidChange(WebCore::StyleDifference, WebCore::RenderStyle const*) WebCore::RenderLayerModelObject::styleDidChange(WebCore::StyleDifference, WebCore::RenderStyle const*) WebCore::RenderBox::styleDidChange(WebCore::StyleDifference, WebCore::RenderStyle const*) WebCore::RenderBlock::styleDidChange(WebCore::StyleDifference, WebCore::RenderStyle const*) WebCore::RenderBlockFlow::styleDidChange(WebCore::StyleDifference, WebCore::RenderStyle const*) WebCore::RenderElement::setStyle(WebCore::RenderStyle&&, WebCore::StyleDifference) WebCore::RenderTreeUpdater::updateRendererStyle(WebCore::RenderElement&, WebCore::RenderStyle&&, WebCore::StyleDifference) WebCore::TimerBase::stop() WebCore::FrameViewLayoutContext::layout() WebCore::FrameView::updateLayoutAndStyleIfNeededRecursive() WebCore::Page::layoutIfNeeded() WebCore::Page::updateRendering() WebKit::WebPage::updateRendering() Scrolling tree commit timer: WebCore::TimerBase::start(WTF::Seconds, WTF::Seconds) WebCore::TimerBase::startOneShot(WTF::Seconds) WebCore::ScrollingCoordinatorMac::scheduleTreeStateCommit() WebCore::AsyncScrollingCoordinator::scrollingStateTreePropertiesChanged() WebCore::ScrollingStateTree::setHasChangedProperties(bool) WebCore::ScrollingStateNode::setPropertyChanged(unsigned int) WebCore::ScrollingStateScrollingNode::setScrollPosition(WebCore::FloatPoint const&) WebCore::AsyncScrollingCoordinator::setScrollingNodeScrollableAreaGeometry(unsigned long long, WebCore::ScrollableArea&) WebCore::RenderLayerCompositor::updateScrollingNodeForScrollingRole(WebCore::RenderLayer&, WebCore::ScrollingTreeState&, WTF::OptionSet<WebCore::RenderLayerCompositor::ScrollingNodeChangeFlags>) WebCore::RenderLayerCompositor::updateScrollCoordinationForLayer(WebCore::RenderLayer&, WebCore::RenderLayer const*, WebCore::ScrollingTreeState&, WTF::OptionSet<WebCore::RenderLayerCompositor::ScrollingNodeChangeFlags>) WebCore::RenderLayerCompositor::updateBackingAndHierarchy(WebCore::RenderLayer&, WTF::Vector<WTF::Ref<WebCore::GraphicsLayer, WTF::DumbPtrTraits<WebCore::GraphicsLayer> >, 0ul, WTF::CrashOnOverflow, 16ul, WTF::FastMalloc>&, WebCore::RenderLayerCompositor::UpdateBackingTraversalState&, WebCore::ScrollingTreeState&, WTF::OptionSet<WebCore::RenderLayerCompositor::UpdateLevel>) WebCore::RenderLayerCompositor::updateCompositingLayers(WebCore::CompositingUpdateType, WebCore::RenderLayer*) WebCore::FrameView::updateCompositingLayersAfterLayout() WebCore::FrameView::didLayout(WTF::WeakPtr<WebCore::RenderElement>) WebCore::FrameViewLayoutContext::layout() WebCore::FrameView::updateLayoutAndStyleIfNeededRecursive() WebCore::Page::layoutIfNeeded() WebCore::Page::updateRendering() WebKit::WebPage::updateRendering() None of these are necessary.
Attachments
Ryosuke Niwa
Comment 1 2020-03-10 23:01:04 PDT
Should we add some flag on Document to indicate that we're in the middle of rendering update?
Ryosuke Niwa
Comment 2 2020-03-10 23:01:58 PDT
Also, in theory, we should never have to schedule style recalc / layout anymore directly.
Rob Buis
Comment 3 2023-07-29 11:20:36 PDT
Rob Buis
Comment 4 2023-07-31 08:48:14 PDT
I think the scheduleLayout case is not happening anymore, at least I could not reproduce it.
Note You need to log in before you can comment on or make changes to this bug.