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:
@@ -88,14 +88,17 @@ sal_Int32 lcl_GetPageCount( sal_uLong nFileSize, short nPageSize )
|
|||||||
}
|
}
|
||||||
|
|
||||||
StgCache::StgCache()
|
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()
|
StgCache::~StgCache()
|
||||||
@@ -122,7 +125,7 @@ void StgCache::SetPhysPageSize( short n )
|
|||||||
rtl::Reference< StgPage > StgCache::Create( sal_Int32 nPg )
|
rtl::Reference< StgPage > StgCache::Create( sal_Int32 nPg )
|
||||||
{
|
{
|
||||||
rtl::Reference< StgPage > xElem( StgPage::Create( nPageSize, nPg ) );
|
rtl::Reference< StgPage > xElem( StgPage::Create( nPageSize, nPg ) );
|
||||||
maLRUCache[ xElem->GetPage() ] = xElem;
|
maLRUPages[ nReplaceIdx++ % maLRUPages.size() ] = xElem;
|
||||||
return xElem;
|
return xElem;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -131,8 +134,14 @@ rtl::Reference< StgPage > StgCache::Create( sal_Int32 nPg )
|
|||||||
void StgCache::Erase( const rtl::Reference< StgPage > &xElem )
|
void StgCache::Erase( const rtl::Reference< StgPage > &xElem )
|
||||||
{
|
{
|
||||||
OSL_ENSURE( xElem.is(), "The pointer should not be NULL!" );
|
OSL_ENSURE( xElem.is(), "The pointer should not be NULL!" );
|
||||||
if ( xElem.is() )
|
if ( xElem.is() ) {
|
||||||
maLRUCache.erase( xElem->GetPage() );
|
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
|
// remove all cache elements without flushing them
|
||||||
@@ -140,16 +149,20 @@ void StgCache::Erase( const rtl::Reference< StgPage > &xElem )
|
|||||||
void StgCache::Clear()
|
void StgCache::Clear()
|
||||||
{
|
{
|
||||||
maDirtyPages.clear();
|
maDirtyPages.clear();
|
||||||
maLRUCache.clear();
|
for ( LRUList::iterator it = maLRUPages.begin(); it != maLRUPages.end(); it++ )
|
||||||
|
it->clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Look for a cached page
|
// Look for a cached page
|
||||||
|
|
||||||
rtl::Reference< StgPage > StgCache::Find( sal_Int32 nPage )
|
rtl::Reference< StgPage > StgCache::Find( sal_Int32 nPage )
|
||||||
{
|
{
|
||||||
IndexToStgPage::iterator aIt = maLRUCache.find( nPage );
|
for ( LRUList::iterator it = maLRUPages.begin(); it != maLRUPages.end(); it++ )
|
||||||
if( aIt != maLRUCache.end() )
|
if ( it->is() && (*it)->GetPage() == nPage )
|
||||||
return (*aIt).second;
|
return *it;
|
||||||
|
IndexToStgPage::iterator it2 = maDirtyPages.find( nPage );
|
||||||
|
if ( it2 != maDirtyPages.end() )
|
||||||
|
return it2->second;
|
||||||
return rtl::Reference< StgPage >();
|
return rtl::Reference< StgPage >();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -199,18 +212,21 @@ rtl::Reference< StgPage > StgCache::Copy( sal_Int32 nNew, sal_Int32 nOld )
|
|||||||
// continue that tradition.
|
// continue that tradition.
|
||||||
sal_Bool StgCache::Commit()
|
sal_Bool StgCache::Commit()
|
||||||
{
|
{
|
||||||
std::vector< StgPage * > aToWrite;
|
if ( Good() ) // otherwise Write does nothing
|
||||||
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;
|
std::vector< StgPage * > aToWrite;
|
||||||
if ( !Write( pPage->GetPage(), pPage->GetData(), 1 ) )
|
for ( IndexToStgPage::iterator aIt = maDirtyPages.begin();
|
||||||
return sal_False;
|
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();
|
maDirtyPages.clear();
|
||||||
@@ -259,6 +275,7 @@ void StgCache::SetStrm( UCBStorageStream* pStgStream )
|
|||||||
|
|
||||||
void StgCache::SetDirty( const rtl::Reference< StgPage > &xPage )
|
void StgCache::SetDirty( const rtl::Reference< StgPage > &xPage )
|
||||||
{
|
{
|
||||||
|
assert( IsWritable() );
|
||||||
maDirtyPages[ xPage->GetPage() ] = xPage;
|
maDirtyPages[ xPage->GetPage() ] = xPage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -33,20 +33,21 @@ class StgPage;
|
|||||||
class StgDirEntry;
|
class StgDirEntry;
|
||||||
class StorageBase;
|
class StorageBase;
|
||||||
|
|
||||||
typedef boost::unordered_map
|
|
||||||
<
|
|
||||||
sal_Int32,
|
|
||||||
rtl::Reference< StgPage >,
|
|
||||||
boost::hash< sal_Int32 >,
|
|
||||||
std::equal_to< sal_Int32 >
|
|
||||||
> IndexToStgPage;
|
|
||||||
|
|
||||||
class StgCache {
|
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_uLong nError; // error code
|
||||||
sal_Int32 nPages; // size of data area in pages
|
sal_Int32 nPages; // size of data area in pages
|
||||||
sal_uInt16 nRef; // reference count
|
sal_uInt16 nRef; // reference count
|
||||||
IndexToStgPage maDirtyPages; // hash of all dirty pages
|
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
|
short nPageSize; // page size of the file
|
||||||
UCBStorageStream* pStorageStream; // holds reference to UCB storage stream
|
UCBStorageStream* pStorageStream; // holds reference to UCB storage stream
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user