From 451c4cccc7e3ec3f1e046d3232cb52f6fc443f59 Mon Sep 17 00:00:00 2001 From: Eike Rathke Date: Sat, 19 Nov 2016 01:11:21 +0100 Subject: [PATCH] sc-perf: bundle SdrObject::BroadcastObjectChange() calls during Save Test doc https://bugs.documentfoundation.org/attachment.cgi?id=128252 from https://bugs.documentfoundation.org/show_bug.cgi?id=103493 ScPostIt::CreateCaptionFromInitData() called through ScDocument::CreateAllNoteCaptions() Incl. Self Called Before: 326,418,830,114 487,308 6,645 After: 145,055,889,118 511,681 6,645 Reduced to 44% or speed-up by factor 2.25 Overall ScDocShell::SaveXML() Before: 370,433,720,090 After: 189,120,982,786 Reduced to 51% or speed-up by factor 1.96 There's still too much broadcasting to accessibility going on though.. Change-Id: I50555fd9751ac24006cc96b2fa8e82b32aba0748 --- include/svx/svdobj.hxx | 20 ++++++++++++++++++++ sc/source/core/data/postit.cxx | 5 +++++ svx/source/svdraw/svdobj.cxx | 29 +++++++++++++++++++++++++++++ 3 files changed, 54 insertions(+) diff --git a/include/svx/svdobj.hxx b/include/svx/svdobj.hxx index 48558684c3b8..b398a19071aa 100644 --- a/include/svx/svdobj.hxx +++ b/include/svx/svdobj.hxx @@ -295,6 +295,7 @@ private: friend class SdrObjListIter; friend class SdrVirtObj; friend class SdrRectObj; + friend class SdrDelayBroadcastObjectChange; protected: Rectangle aOutRect; // surrounding rectangle for Paint (incl. LineWdt, ...) @@ -351,6 +352,11 @@ protected: // #i25616# bool mbSupportTextIndentingOnLineWidthChange : 1; +private: + bool mbDelayBroadcastObjectChange : 1; + mutable bool mbBroadcastObjectChangePending : 1; + +protected: // on import of OLE object from MS documents the BLIP size might be retrieved, // in this case the following member is initialized as nonempty rectangle Rectangle maBLIPSizeRectangle; @@ -968,6 +974,20 @@ private: bool mbDoNotInsertIntoPageAutomatically; }; +/** Suppress BroadcastObjectChange() until destruction of the (last) instance. + Prevents multiple broadcasts for a sequence of calls that would trigger a + broadcast each. Instances may be nested in levels, the outer instance will + trigger the final broadcast. + */ +class SVX_DLLPUBLIC SdrDelayBroadcastObjectChange +{ + SdrObject& mrObj; + bool mbOldDelayBroadcastObjectChange; +public: + SdrDelayBroadcastObjectChange( SdrObject& rObj ); + ~SdrDelayBroadcastObjectChange(); +}; + struct SdrObjCreatorParams { sal_uInt32 nInventor; diff --git a/sc/source/core/data/postit.cxx b/sc/source/core/data/postit.cxx index 18da0ce9367d..623a19913dc9 100644 --- a/sc/source/core/data/postit.cxx +++ b/sc/source/core/data/postit.cxx @@ -640,6 +640,11 @@ void ScPostIt::CreateCaptionFromInitData( const ScAddress& rPos ) const ScNoteCaptionCreator aCreator( mrDoc, rPos, maNoteData ); if( maNoteData.mpCaption ) { + // Prevent triple change broadcasts of the same object, which + // during Save triggered by ScDocument::CreateAllNoteCaptions() + // creates a major performance bottleneck. + SdrDelayBroadcastObjectChange aDelayChange( *maNoteData.mpCaption); + ScCaptionInitData& rInitData = *maNoteData.mxInitData; // transfer ownership of outliner object to caption, or set simple text diff --git a/svx/source/svdraw/svdobj.cxx b/svx/source/svdraw/svdobj.cxx index f87ecd1b6276..0f3de29393c0 100644 --- a/svx/source/svdraw/svdobj.cxx +++ b/svx/source/svdraw/svdobj.cxx @@ -302,6 +302,8 @@ SdrObject::SdrObject() : ,pGrabBagItem(nullptr) ,mnNavigationPosition(SAL_MAX_UINT32) ,mnLayerID(0) + ,mbDelayBroadcastObjectChange(false) + ,mbBroadcastObjectChangePending(false) ,mpSvxShape( nullptr ) ,maWeakUnoShape() ,mbDoNotInsertIntoPageAutomatically(false) @@ -880,6 +882,12 @@ void SdrObject::BroadcastObjectChange() const if( pModel && pModel->isLocked() ) return; + if (mbDelayBroadcastObjectChange) + { + mbBroadcastObjectChangePending = true; + return; + } + bool bPlusDataBroadcast(pPlusData && pPlusData->pBroadcast); bool bObjectChange(IsInserted() && pModel); @@ -3092,6 +3100,27 @@ bool SdrObject::HasText() const return false; } + +SdrDelayBroadcastObjectChange::SdrDelayBroadcastObjectChange( SdrObject& rObj ) : + mrObj(rObj), mbOldDelayBroadcastObjectChange( rObj.mbDelayBroadcastObjectChange) +{ + mrObj.mbDelayBroadcastObjectChange = true; +} + +SdrDelayBroadcastObjectChange::~SdrDelayBroadcastObjectChange() +{ + if (!mbOldDelayBroadcastObjectChange) + { + mrObj.mbDelayBroadcastObjectChange = false; + if (mrObj.mbBroadcastObjectChangePending) + { + mrObj.mbBroadcastObjectChangePending = false; + mrObj.BroadcastObjectChange(); + } + } +} + + SdrObject* SdrObjFactory::CreateObjectFromFactory( sal_uInt32 nInventor, sal_uInt16 nObjIdentifier, SdrPage* , SdrModel* ) { SdrObjCreatorParams aParams { nInventor, nObjIdentifier };