From 540ab389f2adb021a95b5ac52c55c97fc5db5c17 Mon Sep 17 00:00:00 2001 From: Michael Meeks Date: Thu, 20 Sep 2012 11:52:49 +0100 Subject: sot: memory savings to avoid duplicating the whole stream in RAM re-work LRU cache to really be an 8 entry LRU cache. only force dirty pages to stay in memory, hopefully huge reads should now stream through memory. Change-Id: I0bedc762086f5f02202795568743750aefaaa50b --- sot/source/sdstor/stgcache.cxx | 67 ++++++++++++++++++++++++++---------------- sot/source/sdstor/stgcache.hxx | 19 ++++++------ 2 files changed, 52 insertions(+), 34 deletions(-) (limited to 'sot') diff --git a/sot/source/sdstor/stgcache.cxx b/sot/source/sdstor/stgcache.cxx index 06a0ee062273..e787c087640a 100644 --- a/sot/source/sdstor/stgcache.cxx +++ b/sot/source/sdstor/stgcache.cxx @@ -88,14 +88,17 @@ sal_Int32 lcl_GetPageCount( sal_uLong nFileSize, short nPageSize ) } StgCache::StgCache() + : nError( SVSTREAM_OK ) + , nPages( 0 ) + , nRef( 0 ) + , nReplaceIdx( 0 ) + , maLRUPages( 8 ) // entries in the LRU lookup + , nPageSize( 512 ) + , pStorageStream( NULL ) + , pStrm( NULL ) + , bMyStream( sal_False ) + , bFile( sal_False ) { - nRef = 0; - pStrm = NULL; - nPageSize = 512; - nError = SVSTREAM_OK; - bMyStream = sal_False; - bFile = sal_False; - pStorageStream = NULL; } StgCache::~StgCache() @@ -122,7 +125,7 @@ void StgCache::SetPhysPageSize( short n ) rtl::Reference< StgPage > StgCache::Create( sal_Int32 nPg ) { rtl::Reference< StgPage > xElem( StgPage::Create( nPageSize, nPg ) ); - maLRUCache[ xElem->GetPage() ] = xElem; + maLRUPages[ nReplaceIdx++ % maLRUPages.size() ] = xElem; return xElem; } @@ -131,8 +134,14 @@ rtl::Reference< StgPage > StgCache::Create( sal_Int32 nPg ) void StgCache::Erase( const rtl::Reference< StgPage > &xElem ) { OSL_ENSURE( xElem.is(), "The pointer should not be NULL!" ); - if ( xElem.is() ) - maLRUCache.erase( xElem->GetPage() ); + if ( xElem.is() ) { + for ( LRUList::iterator it = maLRUPages.begin(); it != maLRUPages.end(); it++ ) { + if ( it->is() && (*it)->GetPage() == xElem->GetPage() ) { + it->clear(); + break; + } + } + } } // remove all cache elements without flushing them @@ -140,16 +149,20 @@ void StgCache::Erase( const rtl::Reference< StgPage > &xElem ) void StgCache::Clear() { maDirtyPages.clear(); - maLRUCache.clear(); + for ( LRUList::iterator it = maLRUPages.begin(); it != maLRUPages.end(); it++ ) + it->clear(); } // Look for a cached page rtl::Reference< StgPage > StgCache::Find( sal_Int32 nPage ) { - IndexToStgPage::iterator aIt = maLRUCache.find( nPage ); - if( aIt != maLRUCache.end() ) - return (*aIt).second; + for ( LRUList::iterator it = maLRUPages.begin(); it != maLRUPages.end(); it++ ) + if ( it->is() && (*it)->GetPage() == nPage ) + return *it; + IndexToStgPage::iterator it2 = maDirtyPages.find( nPage ); + if ( it2 != maDirtyPages.end() ) + return it2->second; return rtl::Reference< StgPage >(); } @@ -199,18 +212,21 @@ rtl::Reference< StgPage > StgCache::Copy( sal_Int32 nNew, sal_Int32 nOld ) // continue that tradition. sal_Bool StgCache::Commit() { - std::vector< StgPage * > aToWrite; - for ( IndexToStgPage::iterator aIt = maDirtyPages.begin(); - aIt != maDirtyPages.end(); aIt++ ) - aToWrite.push_back( aIt->second.get() ); - - std::sort( aToWrite.begin(), aToWrite.end(), StgPage::IsPageGreater ); - for (std::vector< StgPage * >::iterator aWr = aToWrite.begin(); - aWr != aToWrite.end(); aWr++) + if ( Good() ) // otherwise Write does nothing { - const rtl::Reference< StgPage > &pPage = *aWr; - if ( !Write( pPage->GetPage(), pPage->GetData(), 1 ) ) - return sal_False; + std::vector< StgPage * > aToWrite; + for ( IndexToStgPage::iterator aIt = maDirtyPages.begin(); + aIt != maDirtyPages.end(); aIt++ ) + aToWrite.push_back( aIt->second.get() ); + + std::sort( aToWrite.begin(), aToWrite.end(), StgPage::IsPageGreater ); + for ( std::vector< StgPage * >::iterator aWr = aToWrite.begin(); + aWr != aToWrite.end(); aWr++) + { + const rtl::Reference< StgPage > &pPage = *aWr; + if ( !Write( pPage->GetPage(), pPage->GetData(), 1 ) ) + return sal_False; + } } maDirtyPages.clear(); @@ -259,6 +275,7 @@ void StgCache::SetStrm( UCBStorageStream* pStgStream ) void StgCache::SetDirty( const rtl::Reference< StgPage > &xPage ) { + assert( IsWritable() ); maDirtyPages[ xPage->GetPage() ] = xPage; } diff --git a/sot/source/sdstor/stgcache.hxx b/sot/source/sdstor/stgcache.hxx index 268784683922..e134e2576258 100644 --- a/sot/source/sdstor/stgcache.hxx +++ b/sot/source/sdstor/stgcache.hxx @@ -33,20 +33,21 @@ class StgPage; class StgDirEntry; class StorageBase; -typedef boost::unordered_map -< - sal_Int32, - rtl::Reference< StgPage >, - boost::hash< sal_Int32 >, - std::equal_to< sal_Int32 > -> IndexToStgPage; - class StgCache { + typedef boost::unordered_map + < + sal_Int32, rtl::Reference< StgPage >, + boost::hash< sal_Int32 >, std::equal_to< sal_Int32 > + > IndexToStgPage; + + typedef std::vector< rtl::Reference< StgPage > > LRUList; + sal_uLong nError; // error code sal_Int32 nPages; // size of data area in pages sal_uInt16 nRef; // reference count IndexToStgPage maDirtyPages; // hash of all dirty pages - IndexToStgPage maLRUCache; // hash of index to cached pages + int nReplaceIdx; // index into maLRUPages to replace next + LRUList maLRUPages; // list of last few non-dirty pages. short nPageSize; // page size of the file UCBStorageStream* pStorageStream; // holds reference to UCB storage stream -- cgit