1
0
Fork 0

Improve calculation executor performance (#8851)

* Avoid a copy in CalculationExecutor<CalculationType::Reference>::doEvaluation

* Hack: fixed compilation

* Removed accidentally committed broken assert

* Replaced const_cast hack

* Completed implementation of copyBlockInternalRegister

* Simplified some assert code

* Fixed maintainer compilation
This commit is contained in:
Tobias Gödderz 2019-05-16 11:31:21 +02:00 committed by Michael Hackstein
parent c9fa5fba11
commit 83732bc369
3 changed files with 41 additions and 38 deletions

View File

@ -62,17 +62,17 @@ struct CalculationExecutorInfos : public ExecutorInfos {
CalculationExecutorInfos(CalculationExecutorInfos const&) = delete;
~CalculationExecutorInfos() = default;
RegisterId getOutputRegisterId() const { return _outputRegisterId; }
RegisterId getOutputRegisterId() const noexcept { return _outputRegisterId; }
Query& getQuery() const { return _query; }
Query& getQuery() const noexcept { return _query; }
Expression& getExpression() const { return _expression; }
Expression& getExpression() const noexcept { return _expression; }
std::vector<Variable const*> const& getExpInVars() const {
std::vector<Variable const*> const& getExpInVars() const noexcept {
return _expInVars;
}
std::vector<RegisterId> const& getExpInRegs() const { return _expInRegs; }
std::vector<RegisterId> const& getExpInRegs() const noexcept { return _expInRegs; }
private:
RegisterId _outputRegisterId;
@ -184,7 +184,10 @@ inline void CalculationExecutor<CalculationType::Reference>::doEvaluation(
THROW_ARANGO_EXCEPTION(TRI_ERROR_DEBUG);
}
output.cloneValueInto(_infos.getOutputRegisterId(), input, input.getValue(inRegs[0]));
// We assume here that the output block (which must be the same as the input
// block) is already responsible for this value.
// Thus we do not want to clone it.
output.copyBlockInternalRegister(input, inRegs[0], _infos.getOutputRegisterId());
}
template <CalculationType calculationType>

View File

@ -72,7 +72,7 @@ class InputAqlItemRow {
*
* @return Reference to the AqlValue stored in that variable.
*/
inline const AqlValue& getValue(RegisterId registerId) const {
inline AqlValue const& getValue(RegisterId registerId) const {
TRI_ASSERT(isInitialized());
TRI_ASSERT(registerId < getNrRegisters());
return block().getValueReference(_baseIndex, registerId);

View File

@ -74,22 +74,11 @@ class OutputAqlItemRow {
// responsibility of possibly referenced external memory.
void moveValueInto(RegisterId registerId, InputAqlItemRow const& sourceRow,
AqlValueGuard& guard) {
#ifdef ARANGODB_ENABLE_MAINTAINER_MODE
if (!isOutputRegister(registerId)) {
TRI_ASSERT(false);
THROW_ARANGO_EXCEPTION(TRI_ERROR_WROTE_IN_WRONG_REGISTER);
}
TRI_ASSERT(isOutputRegister(registerId));
// This is already implicitly asserted by isOutputRegister:
TRI_ASSERT(registerId < getNrRegisters());
if (_numValuesWritten >= numRegistersToWrite()) {
TRI_ASSERT(false);
THROW_ARANGO_EXCEPTION(TRI_ERROR_WROTE_TOO_MANY_OUTPUT_REGISTERS);
}
if (!block().getValueReference(_baseIndex, registerId).isNone()) {
TRI_ASSERT(false);
THROW_ARANGO_EXCEPTION(TRI_ERROR_WROTE_OUTPUT_REGISTER_TWICE);
}
#endif
TRI_ASSERT(_numValuesWritten < numRegistersToWrite());
TRI_ASSERT(block().getValueReference(_baseIndex, registerId).isNone());
block().setValue(_baseIndex, registerId, guard.value());
guard.steal();
@ -106,12 +95,7 @@ class OutputAqlItemRow {
// If the reusing does not work this call will return `false` caller needs to
// react accordingly.
bool reuseLastStoredValue(RegisterId registerId, InputAqlItemRow const& sourceRow) {
#ifdef ARANGODB_ENABLE_MAINTAINER_MODE
if (!isOutputRegister(registerId)) {
TRI_ASSERT(false);
THROW_ARANGO_EXCEPTION(TRI_ERROR_WROTE_IN_WRONG_REGISTER);
}
#endif
TRI_ASSERT(isOutputRegister(registerId));
if (_lastBaseIndex == _baseIndex) {
return false;
}
@ -137,8 +121,8 @@ class OutputAqlItemRow {
// This may only be set if the input block is the same as the output block,
// because it is passed through.
if (_doNotCopyInputRow) {
#ifdef ARANGODB_ENABLE_MAINTAINER_MODE
TRI_ASSERT(sourceRow.isInitialized());
#ifdef ARANGODB_ENABLE_MAINTAINER_MODE
TRI_ASSERT(sourceRow.internalBlockIs(_block));
#endif
_inputRowCopied = true;
@ -150,6 +134,30 @@ class OutputAqlItemRow {
doCopyRow(sourceRow, ignoreMissing);
}
void copyBlockInternalRegister(InputAqlItemRow const& sourceRow,
RegisterId input, RegisterId output) {
// This method is only allowed if the block of the input row is the same as
// the block of the output row!
#ifdef ARANGODB_ENABLE_MAINTAINER_MODE
TRI_ASSERT(sourceRow.internalBlockIs(_block));
#endif
TRI_ASSERT(isOutputRegister(output));
// This is already implicitly asserted by isOutputRegister:
TRI_ASSERT(output < getNrRegisters());
TRI_ASSERT(_numValuesWritten < numRegistersToWrite());
TRI_ASSERT(block().getValueReference(_baseIndex, output).isNone());
AqlValue const& value = sourceRow.getValue(input);
block().setValue(_baseIndex, output, value);
_numValuesWritten++;
// allValuesWritten() must be called only *after* _numValuesWritten was
// increased.
if (allValuesWritten()) {
copyRow(sourceRow);
}
}
std::size_t getNrRegisters() const { return block().getNrRegs(); }
/**
@ -158,17 +166,9 @@ class OutputAqlItemRow {
* been called.
*/
void advanceRow() {
#ifdef ARANGODB_ENABLE_MAINTAINER_MODE
TRI_ASSERT(produced());
if (!allValuesWritten()) {
TRI_ASSERT(false);
THROW_ARANGO_EXCEPTION(TRI_ERROR_WROTE_TOO_FEW_OUTPUT_REGISTERS);
}
if (!_inputRowCopied) {
TRI_ASSERT(false);
THROW_ARANGO_EXCEPTION(TRI_ERROR_INPUT_REGISTERS_NOT_COPIED);
}
#endif
TRI_ASSERT(allValuesWritten());
TRI_ASSERT(_inputRowCopied);
_lastBaseIndex = _baseIndex++;
_inputRowCopied = false;
_numValuesWritten = 0;