[Libreoffice-commits] core.git: Branch 'private/kohei/xlsx-import-speedup' - sc/source

Kohei Yoshida kohei.yoshida at collabora.com
Fri Nov 8 19:10:46 CET 2013


 sc/source/filter/oox/formulabuffer.cxx |   85 ++++++++++++++++++++++++++++++++-
 1 file changed, 83 insertions(+), 2 deletions(-)

New commits:
commit 7a3c30d001afbed193958a0b30809b9132782034
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date:   Fri Nov 8 12:33:57 2013 -0500

    Cache previous formula tokens to avoid formula re-compilations.
    
    Change-Id: If20e0ebf5410af0b7655f36f7e4fc06f53d8b14b

diff --git a/sc/source/filter/oox/formulabuffer.cxx b/sc/source/filter/oox/formulabuffer.cxx
index fa8e06a..86c9e6c 100644
--- a/sc/source/filter/oox/formulabuffer.cxx
+++ b/sc/source/filter/oox/formulabuffer.cxx
@@ -34,11 +34,80 @@ using namespace ::com::sun::star::sheet;
 using namespace ::com::sun::star::container;
 
 #include <boost/scoped_ptr.hpp>
+#include <boost/noncopyable.hpp>
 
 namespace oox { namespace xls {
 
 namespace {
 
+/**
+ * Cache the token array for the last cell position in each column. We use
+ * one cache per sheet.
+ */
+class CachedTokenArray : boost::noncopyable
+{
+    struct Item : boost::noncopyable
+    {
+        SCROW mnRow;
+        boost::scoped_ptr<ScTokenArray> mpCode;
+
+        Item() : mnRow(-1), mpCode(NULL) {}
+        Item( SCROW nRow, ScTokenArray* p ) : mnRow(nRow), mpCode(p) {}
+    };
+
+    typedef boost::unordered_map<SCCOL, Item*> ColCacheType;
+    ColCacheType maCache;
+    ScDocument& mrDoc;
+
+public:
+    CachedTokenArray( ScDocument& rDoc ) : mrDoc(rDoc) {}
+
+    ~CachedTokenArray()
+    {
+        ColCacheType::const_iterator it = maCache.begin(), itEnd = maCache.end();
+        for (; it != itEnd; ++it)
+            delete it->second;
+    }
+
+    const ScTokenArray* get( const ScAddress& rPos, const OUString& rFormula ) const
+    {
+        // Check if a token array is cached for this column.
+        ColCacheType::const_iterator it = maCache.find(rPos.Col());
+        if (it == maCache.end())
+            return NULL;
+
+        const Item& rCached = *it->second;
+        ScCompiler aComp(&mrDoc, rPos, *rCached.mpCode);
+        aComp.SetGrammar(formula::FormulaGrammar::GRAM_ENGLISH_XL_OOX);
+        OUStringBuffer aBuf;
+        aComp.CreateStringFromTokenArray(aBuf);
+        OUString aPredicted = aBuf.makeStringAndClear();
+        if (rFormula == aPredicted)
+            return rCached.mpCode.get();
+
+        return NULL;
+    }
+
+    void store( const ScAddress& rPos, const ScTokenArray& rArray )
+    {
+        ColCacheType::iterator it = maCache.find(rPos.Col());
+        if (it == maCache.end())
+        {
+            // Create an entry for this column.
+            std::pair<ColCacheType::iterator,bool> r =
+                maCache.insert(ColCacheType::value_type(rPos.Col(), new Item));
+            if (!r.second)
+                // Insertion failed.
+                return;
+
+            it = r.first;
+        }
+
+        it->second->mnRow = rPos.Row();
+        it->second->mpCode.reset(rArray.Clone());
+    }
+};
+
 void applySharedFormulas(
     ScDocumentImport& rDoc,
     SvNumberFormatter& rFormatter,
@@ -104,7 +173,7 @@ void applySharedFormulas(
 }
 
 void applyCellFormulas(
-    ScDocumentImport& rDoc, SvNumberFormatter& rFormatter,
+    ScDocumentImport& rDoc, CachedTokenArray& rCache, SvNumberFormatter& rFormatter,
     const std::vector<FormulaBuffer::TokenAddressItem>& rCells )
 {
     std::vector<FormulaBuffer::TokenAddressItem>::const_iterator it = rCells.begin(), itEnd = rCells.end();
@@ -112,6 +181,14 @@ void applyCellFormulas(
     {
         ScAddress aPos;
         ScUnoConversion::FillScAddress(aPos, it->maCellAddress);
+        const ScTokenArray* p = rCache.get(aPos, it->maTokenStr);
+        if (p)
+        {
+            // Use the cached version to avoid re-compilation.
+            rDoc.setFormulaCell(aPos, p->Clone());
+            continue;
+        }
+
         ScCompiler aCompiler(&rDoc.getDoc(), aPos);
         aCompiler.SetNumberFormatter(&rFormatter);
         aCompiler.SetGrammar(formula::FormulaGrammar::GRAM_ENGLISH_XL_OOX);
@@ -120,6 +197,7 @@ void applyCellFormulas(
             continue;
 
         rDoc.setFormulaCell(aPos, pCode);
+        rCache.store(aPos, *pCode);
     }
 }
 
@@ -185,7 +263,10 @@ protected:
             applySharedFormulas(mrDoc, *mpFormatter, *mrItem.mpSharedFormulaEntries, *mrItem.mpSharedFormulaIDs);
 
         if (mrItem.mpCellFormulas)
-            applyCellFormulas(mrDoc, *mpFormatter, *mrItem.mpCellFormulas);
+        {
+            CachedTokenArray aCache(mrDoc.getDoc());
+            applyCellFormulas(mrDoc, aCache, *mpFormatter, *mrItem.mpCellFormulas);
+        }
 
         if (mrItem.mpArrayFormulas)
             applyArrayFormulas(mrDoc, *mpFormatter, *mrItem.mpArrayFormulas);


More information about the Libreoffice-commits mailing list