summaryrefslogtreecommitdiff
path: root/sc/source/core/data/formulacell.cxx
diff options
context:
space:
mode:
authorMichael Meeks <michael.meeks@collabora.com>2014-05-23 21:51:14 +0100
committerMichael Meeks <michael.meeks@collabora.com>2014-05-24 21:38:42 +0100
commit4a5d600a0ab8b851bd7565e36be3419066145908 (patch)
treef4c77e80425974a1c4fabf037f6781d0374fb0b6 /sc/source/core/data/formulacell.cxx
parent17fa344d034df1a1179b4e5961ec3001402a6df1 (diff)
ODS load perf: accelerate CompileXML for formula by stringify and compare.
For long columns of repeated formula, it is far faster to convert a formula to a string and compare to see if the next cell in a column matches, than it is to parse the formula string itself (sad but true). This saves 29s of 131s of load time for my (admittedly large) ODS file. Change-Id: I48b613eb7131d6eb3902695aa30a1aa1a9ea5f6a
Diffstat (limited to 'sc/source/core/data/formulacell.cxx')
-rw-r--r--sc/source/core/data/formulacell.cxx48
1 files changed, 45 insertions, 3 deletions
diff --git a/sc/source/core/data/formulacell.cxx b/sc/source/core/data/formulacell.cxx
index ec07bde19cc2..69debafa761c 100644
--- a/sc/source/core/data/formulacell.cxx
+++ b/sc/source/core/data/formulacell.cxx
@@ -1184,9 +1184,51 @@ void ScFormulaCell::CompileXML( sc::CompileFormulaContext& rCxt, ScProgress& rPr
// pCode may not deleted for queries, but must be empty
if ( pCode )
pCode->Clear();
- ScTokenArray* pCodeOld = pCode;
- pCode = aComp.CompileString( aFormula, aFormulaNmsp );
- delete pCodeOld;
+
+ bool bSkipCompile = false;
+
+ static bool bNewPath = getenv ("FASTFORMULA");
+
+ if ( bNewPath && !mxGroup && aFormulaNmsp.isEmpty() ) // optimization
+ {
+ ScAddress aPreviousCell( aPos );
+ aPreviousCell.IncRow( -1 );
+ ScFormulaCell *pPreviousCell = pDocument->GetFormulaCell( aPreviousCell );
+ if( pPreviousCell )
+ {
+ // Now try to convert to a string quickly ...
+ ScCompiler aBackComp( rCxt, aPos, *(pPreviousCell->pCode) );
+ OUStringBuffer aShouldBeBuf;
+ aBackComp.CreateStringFromTokenArray( aShouldBeBuf );
+
+ assert( aFormula[0] == '=' );
+ OUString aShouldBe = aShouldBeBuf.makeStringAndClear();
+ if( aFormula.getLength() == aShouldBe.getLength() + 1 &&
+ aFormula.match( aShouldBe, 1 ) ) // initial '='
+ {
+ // Put them in the same formula group.
+ ScFormulaCellGroupRef xGroup = pPreviousCell->GetCellGroup();
+ if (!xGroup) // Last cell is not grouped yet. Start a new group.
+ xGroup = pPreviousCell->CreateCellGroup(1, false);
+ ++xGroup->mnLength;
+ SetCellGroup( xGroup );
+
+ bSkipCompile = true;
+
+ SAL_INFO( "sc", "merged '" << aFormula << "' == "
+ "'" << aShouldBe << "'" <<
+ " extend group to " << xGroup->mnLength );
+ }
+ }
+ }
+
+ if (!bSkipCompile)
+ {
+ ScTokenArray* pCodeOld = pCode;
+ pCode = aComp.CompileString( aFormula, aFormulaNmsp );
+ delete pCodeOld;
+ }
+
if( !pCode->GetCodeError() )
{
if ( !pCode->GetLen() )