This reasonably trivial fix accelerates a large (private) PivotTable
document load from 100seconds down to 20 seconds for me. It dungs out a
chunk of code - I'm doing some more aggressive cleanup on master - to
not hold the entire OLE2 stream in allocated memory while reading ;-)
[ sadly we still do that while writing until 'Commit' ] - but this is
the simpler version for 3-6.
Review / acks appreciated - it passes 'make check' and some
smoke-testing of load/save big PPT files.
HTH,
Michael.
--
michael.meeks@suse.com <><, Pseudo Engineer, itinerant idiot
From a831889fd2bf7984157053ad250422f077c3ac0e Mon Sep 17 00:00:00 2001
From: Michael Meeks <michael.meeks@suse.com>
Date: Wed, 19 Sep 2012 16:34:28 +0100
Subject: [PATCH] sot: substantially accelerate sorted cache write-out
A simplified version of commit: e48e48910247335124f0726a7fcadb94556883b6
---
sot/source/sdstor/stgcache.cxx | 141 ++++++++--------------------------------
sot/source/sdstor/stgcache.hxx | 9 +--
2 files changed, 30 insertions(+), 120 deletions(-)
diff --git a/sot/source/sdstor/stgcache.cxx b/sot/source/sdstor/stgcache.cxx
index a263e91..01682c5 100644
--- a/sot/source/sdstor/stgcache.cxx
+++ b/sot/source/sdstor/stgcache.cxx
@@ -67,19 +67,13 @@ typedef boost::unordered_map
// a page buffer, even if a read fails. It is up to the caller to determine
// the correctness of the I/O.
-StgPage::StgPage( StgCache* p, short n )
+StgPage::StgPage( StgCache* , short n )
{
OSL_ENSURE( n >= 512, "Unexpected page size is provided!" );
- pCache = p;
nData = n;
bDirty = sal_False;
nPage = 0;
pData = new sal_uInt8[ nData ];
- pNext1 =
- pNext2 =
- pLast1 =
- pLast2 = NULL;
- pOwner = NULL;
}
StgPage::~StgPage()
@@ -99,6 +93,11 @@ void StgPage::SetPage( short nOff, sal_Int32 nVal )
}
}
+bool StgPage::IsPageGreater( const StgPage *pA, const StgPage *pB )
+{
+ return pA->nPage < pB->nPage;
+}
+
//////////////////////////////// class StgCache ////////////////////////////
// The disk cache holds the cached sectors. The sector type differ according
@@ -115,7 +114,6 @@ StgCache::StgCache()
{
nRef = 0;
pStrm = NULL;
- pCur = pElem1 = NULL;
nPageSize = 512;
nError = SVSTREAM_OK;
bMyStream = sal_False;
@@ -145,7 +143,6 @@ void StgCache::SetPhysPageSize( short n )
}
// Create a new cache element
-// pCur points to this element
StgPage* StgCache::Create( sal_Int32 nPg )
{
@@ -154,40 +151,10 @@ StgPage* StgCache::Create( sal_Int32 nPg )
// For data security, clear the buffer contents
memset( pElem->pData, 0, pElem->nData );
- // insert to LRU
- if( pCur )
- {
- pElem->pNext1 = pCur;
- pElem->pLast1 = pCur->pLast1;
- pElem->pNext1->pLast1 =
- pElem->pLast1->pNext1 = pElem;
- }
- else
- pElem->pNext1 = pElem->pLast1 = pElem;
if( !pLRUCache )
pLRUCache = new UsrStgPagePtr_Impl();
(*(UsrStgPagePtr_Impl*)pLRUCache)[pElem->nPage] = pElem;
- pCur = pElem;
- // insert to Sorted
- if( !pElem1 )
- pElem1 = pElem->pNext2 = pElem->pLast2 = pElem;
- else
- {
- StgPage* p = pElem1;
- do
- {
- if( pElem->nPage < p->nPage )
- break;
- p = p->pNext2;
- } while( p != pElem1 );
- pElem->pNext2 = p;
- pElem->pLast2 = p->pLast2;
- pElem->pNext2->pLast2 =
- pElem->pLast2->pNext2 = pElem;
- if( p->nPage < pElem1->nPage )
- pElem1 = pElem;
- }
return pElem;
}
@@ -198,19 +165,8 @@ void StgCache::Erase( StgPage* pElem )
OSL_ENSURE( pElem, "The pointer should not be NULL!" );
if ( pElem )
{
- OSL_ENSURE( pElem->pNext1 && pElem->pLast1, "The pointers may not be NULL!" );
- //remove from LRU
- pElem->pNext1->pLast1 = pElem->pLast1;
- pElem->pLast1->pNext1 = pElem->pNext1;
- if( pCur == pElem )
- pCur = ( pElem->pNext1 == pElem ) ? NULL : pElem->pNext1;
if( pLRUCache )
((UsrStgPagePtr_Impl*)pLRUCache)->erase( pElem->nPage );
- // remove from Sorted
- pElem->pNext2->pLast2 = pElem->pLast2;
- pElem->pLast2->pNext2 = pElem->pNext2;
- if( pElem1 == pElem )
- pElem1 = ( pElem->pNext2 == pElem ) ? NULL : pElem->pNext2;
delete pElem;
}
}
@@ -219,16 +175,6 @@ void StgCache::Erase( StgPage* pElem )
void StgCache::Clear()
{
- StgPage* pElem = pCur;
- if( pCur ) do
- {
- StgPage* pDelete = pElem;
- pElem = pElem->pNext1;
- delete pDelete;
- }
- while( pCur != pElem );
- pCur = NULL;
- pElem1 = NULL;
delete (UsrStgPagePtr_Impl*)pLRUCache;
pLRUCache = NULL;
}
@@ -245,19 +191,6 @@ StgPage* StgCache::Find( sal_Int32 nPage )
// page found
StgPage* pFound = (*aIt).second;
OSL_ENSURE( pFound, "The pointer may not be NULL!" );
-
- if( pFound != pCur )
- {
- OSL_ENSURE( pFound->pNext1 && pFound->pLast1, "The pointers may not be NULL!" );
- // remove from LRU
- pFound->pNext1->pLast1 = pFound->pLast1;
- pFound->pLast1->pNext1 = pFound->pNext1;
- // insert to LRU
- pFound->pNext1 = pCur;
- pFound->pLast1 = pCur->pLast1;
- pFound->pNext1->pLast1 =
- pFound->pLast1->pNext1 = pFound;
- }
return pFound;
}
return NULL;
@@ -304,52 +237,34 @@ StgPage* StgCache::Copy( sal_Int32 nNew, sal_Int32 nOld )
return p;
}
-// Flush the cache whose owner is given. NULL flushes all.
+// Historically this wrote pages in a sorted, ascending order;
+// continue that tradition.
sal_Bool StgCache::Commit()
{
- StgPage* p = pElem1;
- if( p ) do
+ UsrStgPagePtr_Impl *pCache = (UsrStgPagePtr_Impl*)pLRUCache;
+
+ std::vector< StgPage * > aToWrite;
+ for ( UsrStgPagePtr_Impl::iterator aIt = pCache->begin();
+ aIt != pCache->end(); aIt++ )
{
- if( p->bDirty )
- {
- sal_Bool b = Write( p->nPage, p->pData, 1 );
- if( !b )
- return sal_False;
- p->bDirty = sal_False;
- }
- p = p->pNext2;
- } while( p != pElem1 );
+ if ( aIt->second->bDirty )
+ aToWrite.push_back( aIt->second );
+ }
+
+ std::sort( aToWrite.begin(), aToWrite.end(), StgPage::IsPageGreater );
+ for (std::vector< StgPage * >::iterator aWr = aToWrite.begin();
+ aWr != aToWrite.end(); aWr++)
+ {
+ StgPage *pPage = *aWr;
+ if ( !Write( pPage->GetPage(), pPage->GetData(), 1 ) )
+ return sal_False;
+ pPage->bDirty = sal_False;
+ }
+
pStrm->Flush();
SetError( pStrm->GetError() );
-#ifdef CHECK_DIRTY
- p = pElem1;
- if( p ) do
- {
- if( p->bDirty )
- {
- ErrorBox( NULL, WB_OK, String("SO2: Dirty Block in Ordered List") ).Execute();
- sal_Bool b = Write( p->nPage, p->pData, 1 );
- if( !b )
- return sal_False;
- p->bDirty = sal_False;
- }
- p = p->pNext2;
- } while( p != pElem1 );
- p = pElem1;
- if( p ) do
- {
- if( p->bDirty )
- {
- ErrorBox( NULL, WB_OK, String("SO2: Dirty Block in LRU List") ).Execute();
- sal_Bool b = Write( p->nPage, p->pData, 1 );
- if( !b )
- return sal_False;
- p->bDirty = sal_False;
- }
- p = p->pNext1;
- } while( p != pElem1 );
-#endif
+
return sal_True;
}
diff --git a/sot/source/sdstor/stgcache.hxx b/sot/source/sdstor/stgcache.hxx
index 4ea16d3..e2d0a06 100644
--- a/sot/source/sdstor/stgcache.hxx
+++ b/sot/source/sdstor/stgcache.hxx
@@ -42,8 +42,6 @@ class StgDirEntry;
class StorageBase;
class StgCache {
- StgPage* pCur; // top of LRU list
- StgPage* pElem1; // top of ordered list
sal_uLong nError; // error code
sal_Int32 nPages; // size of data area in pages
sal_uInt16 nRef; // reference count
@@ -93,10 +91,6 @@ public:
class StgPage {
friend class StgCache;
- StgCache* pCache; // the cache
- StgPage *pNext1, *pLast1; // LRU chain
- StgPage *pNext2, *pLast2; // ordered chain
- StgDirEntry* pOwner; // owner
sal_Int32 nPage; // page #
sal_uInt8* pData; // nPageSize characters
short nData; // size of this page
@@ -108,7 +102,7 @@ public:
sal_Int32 GetPage() { return nPage; }
void* GetData() { return pData; }
short GetSize() { return nData; }
- void SetOwner( StgDirEntry* p ) { pOwner = p; }
+ void SetOwner( StgDirEntry* ) { }
// routines for accessing FAT pages
// Assume that the data is a FAT page and get/put FAT data.
sal_Int32 GetPage( short nOff )
@@ -123,6 +117,7 @@ public:
#endif
}
void SetPage( short, sal_Int32 ); // put an element
+ static bool IsPageGreater( const StgPage *pA, const StgPage *pB );
};
#endif
--
1.7.10.4
Context
- [REVIEW 3-6] acclerate large OLE2 file reading ... · Michael Meeks
Privacy Policy |
Impressum (Legal Info) |
Copyright information: Unless otherwise specified, all text and images
on this website are licensed under the
Creative Commons Attribution-Share Alike 3.0 License.
This does not include the source code of LibreOffice, which is
licensed under the Mozilla Public License (
MPLv2).
"LibreOffice" and "The Document Foundation" are
registered trademarks of their corresponding registered owners or are
in actual use as trademarks in one or more countries. Their respective
logos and icons are also subject to international copyright laws. Use
thereof is explained in our
trademark policy.