Kaydet (Commit) f18cb2c1 authored tarafından Markus Mohrhard's avatar Markus Mohrhard Kaydeden (comit) Markus Mohrhard

single element access is really slow in mdds, tdf#67071

Change-Id: I5491ba0bc44a9ce8844b31126835671c5d5abcaa
Reviewed-on: https://gerrit.libreoffice.org/22386Tested-by: 's avatarJenkins <ci@libreoffice.org>
Reviewed-by: 's avatarMarkus Mohrhard <markus.mohrhard@googlemail.com>
üst fe90ba29
......@@ -123,6 +123,10 @@ protected:
public:
enum Op { Add, Sub, Mul, Div };
typedef std::function<void(size_t, size_t, double)> DoubleOpFunction;
typedef std::function<void(size_t, size_t, bool)> BoolOpFunction;
typedef std::function<void(size_t, size_t, svl::SharedString)> StringOpFunction;
/**
* When adding all numerical matrix elements for a scalar result such as
* summation, the interpreter wants to separate the first non-zero value
......@@ -393,6 +397,9 @@ public:
virtual std::vector<ScMatrix::IterateResult> Collect(bool bTextAsZero, const std::vector<std::unique_ptr<sc::op::Op>>& aOp) = 0;
virtual void ExecuteOperation(const std::pair<size_t, size_t>& rStartPos, const std::pair<size_t, size_t>& rEndPos,
DoubleOpFunction aDoubleFunc, BoolOpFunction aBoolFunc, StringOpFunction aStringFunc) const = 0;
#if DEBUG_MATRIX
void Dump() const;
#endif
......@@ -598,6 +605,8 @@ public:
virtual std::vector<ScMatrix::IterateResult> Collect(bool bTextAsZero, const std::vector<std::unique_ptr<sc::op::Op>>& aOp) override;
virtual void ExecuteOperation(const std::pair<size_t, size_t>& rStartPos, const std::pair<size_t, size_t>& rEndPos,
DoubleOpFunction aDoubleFunc, BoolOpFunction aBoolFunc, StringOpFunction aStringFunc) const;
ScFullMatrix& operator+= ( const ScFullMatrix& r );
#if DEBUG_MATRIX
......@@ -806,6 +815,9 @@ public:
virtual std::vector<ScMatrix::IterateResult> Collect(bool bTextAsZero, const std::vector<std::unique_ptr<sc::op::Op>>& aOp) override;
virtual void ExecuteOperation(const std::pair<size_t, size_t>& rStartPos, const std::pair<size_t, size_t>& rEndPos,
DoubleOpFunction aDoubleFunc, BoolOpFunction aBoolFunc, StringOpFunction aStringFunc) const;
ScVectorRefMatrix& operator+=(const ScVectorRefMatrix& r);
};
......
......@@ -300,6 +300,10 @@ public:
template<typename T>
void ApplyOperation(T aOp, ScMatrixImpl& rMat);
void ExecuteOperation(const std::pair<size_t, size_t>& rStartPos,
const std::pair<size_t, size_t>& rEndPos, ScFullMatrix::DoubleOpFunction aDoubleFunc,
ScFullMatrix::BoolOpFunction aBoolFunc, ScFullMatrix::StringOpFunction aStringFunc) const;
template<typename T>
std::vector<ScMatrix::IterateResult> ApplyCollectOperation(bool bTextAsZero, const std::vector<std::unique_ptr<T>>& aOp);
......@@ -2169,6 +2173,117 @@ std::vector<ScMatrix::IterateResult> ScMatrixImpl::ApplyCollectOperation(bool bT
return aFunc.getResult();
}
namespace {
class WalkElementBlockOperation
{
public:
WalkElementBlockOperation(size_t nRowSize, size_t /*nColSize*/,
ScFullMatrix::DoubleOpFunction aDoubleFunc,
ScFullMatrix::BoolOpFunction aBoolFunc,
ScFullMatrix::StringOpFunction aStringFunc):
mnRowSize(nRowSize),
mnRowPos(0),
mnColPos(0),
maDoubleFunc(aDoubleFunc),
maBoolFunc(aBoolFunc),
maStringFunc(aStringFunc)
{
}
void operator()(const MatrixImplType::element_block_node_type& node)
{
switch (node.type)
{
case mdds::mtm::element_numeric:
{
typedef MatrixImplType::numeric_block_type block_type;
block_type::const_iterator it = block_type::begin(*node.data);
std::advance(it, node.offset);
block_type::const_iterator itEnd = it;
std::advance(itEnd, node.size);
for (auto itr = it; itr != itEnd; ++itr)
{
maDoubleFunc(mnRowPos, mnColPos, *itr);
++mnRowPos;
if (mnRowPos >= mnRowSize)
{
mnRowPos = 0;
++mnColPos;
}
}
}
break;
case mdds::mtm::element_string:
{
typedef MatrixImplType::string_block_type block_type;
block_type::const_iterator it = block_type::begin(*node.data);
std::advance(it, node.offset);
block_type::const_iterator itEnd = it;
std::advance(itEnd, node.size);
for (auto itr = it; itr != itEnd; ++itr)
{
maStringFunc(mnRowPos, mnColPos, *itr);
++mnRowPos;
if (mnRowPos >= mnRowSize)
{
mnRowPos = 0;
++mnColPos;
}
}
}
break;
case mdds::mtm::element_boolean:
{
typedef MatrixImplType::boolean_block_type block_type;
block_type::const_iterator it = block_type::begin(*node.data);
std::advance(it, node.offset);
block_type::const_iterator itEnd = it;
std::advance(itEnd, node.size);
for (auto itr = it; itr != itEnd; ++itr)
{
maBoolFunc(mnRowPos, mnColPos, *itr);
++mnRowPos;
if (mnRowPos >= mnRowSize)
{
mnRowPos = 0;
++mnColPos;
}
}
}
break;
case mdds::mtm::element_empty:
break;
}
}
private:
size_t mnRowSize;
size_t mnRowPos;
size_t mnColPos;
ScFullMatrix::DoubleOpFunction maDoubleFunc;
ScFullMatrix::BoolOpFunction maBoolFunc;
ScFullMatrix::StringOpFunction maStringFunc;
};
}
void ScMatrixImpl::ExecuteOperation(const std::pair<size_t, size_t>& rStartPos,
const std::pair<size_t, size_t>& rEndPos, ScMatrix::DoubleOpFunction aDoubleFunc,
ScMatrix::BoolOpFunction aBoolFunc, ScMatrix::StringOpFunction aStringFunc) const
{
WalkElementBlockOperation aFunc(maMat.size().row, maMat.size().column,
aDoubleFunc, aBoolFunc, aStringFunc);
maMat.walk(aFunc, MatrixImplType::size_pair_type(rStartPos.first, rStartPos.second),
MatrixImplType::size_pair_type(rEndPos.first, rEndPos.second));
}
#if DEBUG_MATRIX
void ScMatrixImpl::Dump() const
......@@ -2817,6 +2932,13 @@ void ScFullMatrix::PowOp( bool bFlag, double fVal, ScMatrix& rMat)
}
}
void ScFullMatrix::ExecuteOperation(const std::pair<size_t, size_t>& rStartPos,
const std::pair<size_t, size_t>& rEndPos, DoubleOpFunction aDoubleFunc,
BoolOpFunction aBoolFunc, StringOpFunction aStringFunc) const
{
pImpl->ExecuteOperation(rStartPos, rEndPos, aDoubleFunc, aBoolFunc, aStringFunc);
}
std::vector<ScMatrix::IterateResult> ScFullMatrix::Collect(bool bTextAsZero, const std::vector<std::unique_ptr<sc::op::Op>>& aOp)
{
return pImpl->ApplyCollectOperation(bTextAsZero, aOp);
......@@ -3555,4 +3677,12 @@ std::vector<ScMatrix::IterateResult> ScVectorRefMatrix::Collect(bool bTextAsZero
return mpFullMatrix->Collect(bTextAsZero, aOp);
}
void ScVectorRefMatrix::ExecuteOperation(const std::pair<size_t, size_t>& rStartPos,
const std::pair<size_t, size_t>& rEndPos, DoubleOpFunction aDoubleFunc,
BoolOpFunction aBoolFunc, StringOpFunction aStringFunc) const
{
const_cast<ScVectorRefMatrix*>(this)->ensureFullMatrix();
mpFullMatrix->ExecuteOperation(rStartPos, rEndPos, aDoubleFunc, aBoolFunc, aStringFunc);
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
......@@ -791,35 +791,21 @@ void ScExternalRefCache::setCellRangeData(sal_uInt16 nFileId, const ScRange& rRa
pTabData.reset(new Table);
const ScMatrixRef& pMat = itrData->mpRangeData;
for (SCROW nRow = nRow1; nRow <= nRow2; ++nRow)
ScFullMatrix::DoubleOpFunction aDoubleFunc = [=](size_t row, size_t col, double val) -> void
{
const SCSIZE nR = nRow - nRow1;
for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol)
{
const SCSIZE nC = nCol - nCol1;
ScMatrixValue value = pMat->Get(nC, nR);
TokenRef pToken;
switch (value.nType) {
case SC_MATVAL_VALUE:
case SC_MATVAL_BOOLEAN:
pToken.reset(new formula::FormulaDoubleToken(value.fVal));
break;
case SC_MATVAL_STRING:
pToken.reset(new formula::FormulaStringToken(value.aStr));
break;
default:
// Don't cache empty cells.
break;
}
if (pToken)
// Don't mark this cell 'cached' here, for better performance.
pTabData->setCell(nCol, nRow, pToken, 0, false);
}
}
pTabData->setCell(col + nCol1, row + nRow1, new formula::FormulaDoubleToken(val), 0, false);
};
ScFullMatrix::BoolOpFunction aBoolFunc = [=](size_t row, size_t col, bool val) -> void
{
pTabData->setCell(col + nCol1, row + nRow1, new formula::FormulaDoubleToken(val), 0, false);
};
ScFullMatrix::StringOpFunction aStringFunc = [=](size_t row, size_t col, svl::SharedString val) -> void
{
pTabData->setCell(col + nCol1, row + nRow1, new formula::FormulaStringToken(val), 0, false);
};
pMat->ExecuteOperation(std::pair<size_t, size_t>(0, 0),
std::pair<size_t, size_t>(nRow2-nRow1, nCol2-nCol1),
aDoubleFunc, aBoolFunc, aStringFunc);
// Mark the whole range 'cached'.
pTabData->setCachedCellRange(nCol1, nRow1, nCol2, nRow2);
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment