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
This commit is contained in:
Michael Meeks
2012-09-20 11:52:49 +01:00
parent f3b2fc9be2
commit 540ab389f2
2 changed files with 52 additions and 34 deletions

View File

@@ -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;
}

View File

@@ -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