summaryrefslogtreecommitdiff
path: root/svtools
diff options
context:
space:
mode:
authorArmin Le Grand <alg@apache.org>2014-06-19 16:49:26 +0000
committerCaolán McNamara <caolanm@redhat.com>2014-07-15 16:15:17 +0100
commit0ca0202a0994c0b7c99c366fd5cafd8a655df203 (patch)
tree216ae67a2efefa657415446e7f7852a51bc18f88 /svtools
parent146c2e006ef5974ea952ce96eba0109c182db237 (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.cxx50
-rw-r--r--svtools/source/graphic/grfmgr2.cxx79
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 )