diff options
author | Armin Le Grand <alg@apache.org> | 2014-06-19 16:49:26 +0000 |
---|---|---|
committer | Caolán McNamara <caolanm@redhat.com> | 2014-07-15 16:15:17 +0100 |
commit | 0ca0202a0994c0b7c99c366fd5cafd8a655df203 (patch) | |
tree | 216ae67a2efefa657415446e7f7852a51bc18f88 /svtools | |
parent | 146c2e006ef5974ea952ce96eba0109c182db237 (diff) |
Resolves: #i125111# limit mem footprint for GraphicObjects...
in 32Bit environments
Conflicts:
svtools/inc/svtools/grfmgr.hxx
svtools/source/graphic/grfmgr.cxx
svtools/source/graphic/grfmgr2.cxx
sw/source/core/doc/notxtfrm.cxx
sw/source/core/graphic/ndgrf.cxx
"commit 62b0eaf37c08dd27244e77b8bc90c691b000ebd6
Related: fdo#50697 reset the cache timeout on GetGraphic
so the graphic gets swapped out Xms after the last use and not Xms after
initial creation regardless of if it got used a moment earlier."
corrected place for stl sort function for linux
(cherry picked from commit a48414a396f7de4e00510e82e3744c097ce3d5d6)
Conflicts:
svtools/source/graphic/grfmgr2.cxx
Change-Id: I79158b7d42629f8dec2bc5565540701bcd3ef6f4
6f21c7fd4d2681446fc1a6d9607366a1e69165a1
Diffstat (limited to 'svtools')
-rw-r--r-- | svtools/source/graphic/grfmgr.cxx | 50 | ||||
-rw-r--r-- | svtools/source/graphic/grfmgr2.cxx | 79 |
2 files changed, 118 insertions, 11 deletions
diff --git a/svtools/source/graphic/grfmgr.cxx b/svtools/source/graphic/grfmgr.cxx index 408081ebc40f..1402ea71fbc7 100644 --- a/svtools/source/graphic/grfmgr.cxx +++ b/svtools/source/graphic/grfmgr.cxx @@ -59,6 +59,19 @@ struct GrfSimpleCacheObj TYPEINIT1_AUTOFACTORY( GraphicObject, SvDataCopyStream ); +// unique increasing ID for being able to detect the GraphicObject with the +// oldest last data changes +static sal_uLong aIncrementingTimeOfLastDataChange = 1; + +void GraphicObject::ImplAfterDataChange() +{ + // set unique timestamp ID of last data change + mnDataChangeTimeStamp = aIncrementingTimeOfLastDataChange++; + + // check memory footprint of all GraphicObjects managed and evtl. take action + GetGraphicManager().ImplCheckSizeOfSwappedInGraphics(); +} + GraphicObject::GraphicObject( const GraphicManager* pMgr ) : maLink (), maUserData () @@ -130,6 +143,9 @@ void GraphicObject::ImplConstruct() mbAutoSwapped = false; mbIsInSwapIn = false; mbIsInSwapOut = false; + + // Init with a unique, increasing ID + mnDataChangeTimeStamp = aIncrementingTimeOfLastDataChange++; } void GraphicObject::ImplAssignGraphicData() @@ -243,6 +259,9 @@ void GraphicObject::ImplAutoSwapIn() if( !mbAutoSwapped && mpMgr ) mpMgr->ImplGraphicObjectWasSwappedIn( *this ); } + + // Handle evtl. needed AfterDataChanges + ImplAfterDataChange(); } } @@ -744,15 +763,6 @@ void GraphicObject::StopAnimation( OutputDevice* pOut, long nExtraData ) mpSimpleCache->maGraphic.StopAnimation( pOut, nExtraData ); } -void GraphicObject::ResetCacheTimeOut() -{ - if (mpSwapOutTimer) - { - mpSwapOutTimer->Stop(); - mpSwapOutTimer->Start(); - } -} - const Graphic& GraphicObject::GetGraphic() const { GraphicObject *pThis = const_cast<GraphicObject*>(this); @@ -763,7 +773,7 @@ const Graphic& GraphicObject::GetGraphic() const //fdo#50697 If we've been asked to provide the graphic, then reset //the cache timeout to start from now and not remain at the //time of creation - pThis->ResetCacheTimeOut(); + pThis->restartSwapOutTimer(); return maGraphic; } @@ -785,6 +795,9 @@ void GraphicObject::SetGraphic( const Graphic& rGraphic, const GraphicObject* pC if( mpSwapOutTimer ) mpSwapOutTimer->Start(); + + // Handle evtl. needed AfterDataChanges + ImplAfterDataChange(); } void GraphicObject::SetGraphic( const Graphic& rGraphic, const OUString& rLink ) @@ -1101,7 +1114,9 @@ bool GraphicObject::SwapIn() bRet = true; } else if( mpMgr && mpMgr->ImplFillSwappedGraphicObject( *this, maGraphic ) ) + { bRet = true; + } else { bRet = maGraphic.SwapIn(); @@ -1111,8 +1126,13 @@ bool GraphicObject::SwapIn() } if( bRet ) + { ImplAssignGraphicData(); + // Handle evtl. needed AfterDataChanges + ImplAfterDataChange(); + } + return bRet; } @@ -1297,4 +1317,14 @@ basegfx::B2DVector GraphicObject::calculateCropScaling( return basegfx::B2DVector(fFactorX,fFactorY); } +// restart SwapOut timer +void GraphicObject::restartSwapOutTimer() const +{ + if( mpSwapOutTimer && mpSwapOutTimer->IsActive() ) + { + mpSwapOutTimer->Stop(); + mpSwapOutTimer->Start(); + } +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svtools/source/graphic/grfmgr2.cxx b/svtools/source/graphic/grfmgr2.cxx index 117a4d0121e7..d5731d8cde9a 100644 --- a/svtools/source/graphic/grfmgr2.cxx +++ b/svtools/source/graphic/grfmgr2.cxx @@ -64,6 +64,11 @@ void GraphicManager::SetMaxCacheSize( sal_uLong nNewCacheSize ) mpCache->SetMaxDisplayCacheSize( nNewCacheSize ); } +sal_uLong GraphicManager::GetMaxCacheSize() const +{ + return mpCache->GetMaxDisplayCacheSize(); +} + void GraphicManager::SetMaxObjCacheSize( sal_uLong nNewMaxObjSize, bool bDestroyGreaterCached ) { mpCache->SetMaxObjDisplayCacheSize( nNewMaxObjSize, bDestroyGreaterCached ); @@ -171,9 +176,81 @@ OString GraphicManager::ImplGetUniqueID( const GraphicObject& rObj ) const return mpCache->GetUniqueID( rObj ); } +namespace +{ + struct simpleSortByDataChangeTimeStamp + { + bool operator() (GraphicObject* p1, GraphicObject* p2) const + { + return p1->GetDataChangeTimeStamp() < p2->GetDataChangeTimeStamp(); + } + }; +} // end of anonymous namespace + +void GraphicManager::ImplCheckSizeOfSwappedInGraphics() +{ + // only necessary for 32bit systems + if(SAL_TYPES_SIZEOFPOINTER <= 4) + { + // get the currently used memory footprint of all swapped in bitmap graphics + // of this graphic manager. Remember candidates in a vector. The size in bytes is + // already available, thus this loop is not expensive to execute + sal_uLong nUsedSize(0); + GraphicObject* pObj = 0; + std::vector< GraphicObject* > aCandidates; + + for (size_t i = 0, n = maObjList.size(); i < n; ++i) + { + pObj = maObjList[i]; + if (pObj->meType == GRAPHIC_BITMAP && !pObj->IsSwappedOut() && pObj->GetSizeBytes()) + { + aCandidates.push_back(pObj); + nUsedSize += pObj->GetSizeBytes(); + } + } + + // detect maximum allowed memory footprint. Use the user-settings of MaxCacheSize (defaulted + // to 20MB) and add a decent multiplicator (expecrimented to find one). Limit to + // a useful maximum for 32Bit address space + + // default is 20MB, so allow 200MB initially + static sal_uLong aMultiplicator(10); + + // max at 500MB; I experimented with 800 for debug and 750 for non-debug settings (pics start + // missing when office reaches a mem footprint of 1.5GB) but some secure left over space for + // app activity is needed + static sal_uLong aMaxSize32Bit(500 * 1024 * 1024); + + // calc max allowed cache size + const sal_uLong nMaxCacheSize(::std::min(GetMaxCacheSize() * aMultiplicator, aMaxSize32Bit)); + + if(nUsedSize >= nMaxCacheSize && !aCandidates.empty()) + { + // if we use more currently, sort by last DataChangeTimeStamp + // sort by DataChangeTimeStamp so that the oldest get removed first + ::std::sort(aCandidates.begin(), aCandidates.end(), simpleSortByDataChangeTimeStamp()); + + for(sal_uInt32 a(0); nUsedSize >= nMaxCacheSize && a < aCandidates.size(); a++) + { + // swap out until we have no more or the goal to use less than nMaxCacheSize + // is reached + pObj = aCandidates[a]; + const sal_uLong nSizeBytes(pObj->GetSizeBytes()); + + // do not swap out when we have less than 16KB data objects + if(nSizeBytes >= (16 * 1024)) + { + pObj->FireSwapOutRequest(); + nUsedSize = (nSizeBytes < nUsedSize) ? nUsedSize - nSizeBytes : 0; + } + } + } + } +} + bool GraphicManager::ImplFillSwappedGraphicObject( const GraphicObject& rObj, Graphic& rSubstitute ) { - return( mpCache->FillSwappedGraphicObject( rObj, rSubstitute ) ); + return mpCache->FillSwappedGraphicObject(rObj, rSubstitute); } void GraphicManager::ImplGraphicObjectWasSwappedIn( const GraphicObject& rObj ) |