mirror of https://gitee.com/bigwinds/arangodb
Implement clear unneeded registers.
This commit is contained in:
parent
e5f09bfd87
commit
8fd6cd1184
|
@ -118,6 +118,34 @@ void AqlItemBlock::shrink (size_t nrItems) {
|
|||
_nrItems = nrItems;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief clears out some columns (registers), this deletes the values if
|
||||
/// necessary, using the reference count.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void AqlItemBlock::clearRegisters (std::unordered_set<RegisterId>& toClear) {
|
||||
for (auto reg : toClear) {
|
||||
for (size_t i = 0; i < _nrItems; i++) {
|
||||
AqlValue& a(_data[_nrRegs * i + reg]);
|
||||
if (! a.isEmpty()) {
|
||||
auto it = _valueCount.find(a);
|
||||
if (it != _valueCount.end()) {
|
||||
if (--it->second == 0) {
|
||||
try {
|
||||
_valueCount.erase(it);
|
||||
}
|
||||
catch (...) {
|
||||
it->second++;
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
a.erase();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief slice/clone, this does a deep copy of all entries
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -239,6 +239,13 @@ namespace triagens {
|
|||
|
||||
void shrink (size_t nrItems);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief clears out some columns (registers), this deletes the values if
|
||||
/// necessary, using the reference count.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void clearRegisters (std::unordered_set<RegisterId>& toClear);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief slice/clone, this does a deep copy of all entries
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -194,6 +194,45 @@ void ExecutionBlock::walk (WalkerWorker<ExecutionBlock>* worker) {
|
|||
/// @brief static analysis
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct StaticAnalysisDebugger : public WalkerWorker<ExecutionBlock> {
|
||||
StaticAnalysisDebugger () : indent(0) {};
|
||||
~StaticAnalysisDebugger () {};
|
||||
|
||||
int indent;
|
||||
|
||||
bool enterSubquery (ExecutionBlock* super, ExecutionBlock* sub) {
|
||||
indent++;
|
||||
return true;
|
||||
}
|
||||
|
||||
void leaveSubquery (ExecutionBlock* super, ExecutionBlock* sub) {
|
||||
indent--;
|
||||
}
|
||||
|
||||
void after (ExecutionBlock* eb) {
|
||||
ExecutionNode const* ep = eb->getPlanNode();
|
||||
for (int i = 0; i < indent; i++) {
|
||||
std::cout << " ";
|
||||
}
|
||||
std::cout << ep->getTypeString() << " ";
|
||||
std::cout << "regsUsedHere: ";
|
||||
for (auto v : ep->getVariablesUsedHere()) {
|
||||
std::cout << eb->_varOverview->varInfo.find(v->id)->second.registerId
|
||||
<< " ";
|
||||
}
|
||||
std::cout << "regsSetHere: ";
|
||||
for (auto v : ep->getVariablesSetHere()) {
|
||||
std::cout << eb->_varOverview->varInfo.find(v->id)->second.registerId
|
||||
<< " ";
|
||||
}
|
||||
std::cout << "regsToClear: ";
|
||||
for (auto r : eb->_regsToClear) {
|
||||
std::cout << r << " ";
|
||||
}
|
||||
std::cout << std::endl;
|
||||
}
|
||||
};
|
||||
|
||||
void ExecutionBlock::staticAnalysis (ExecutionBlock* super) {
|
||||
// The super is only for the case of subqueries.
|
||||
shared_ptr<VarOverview> v;
|
||||
|
@ -211,6 +250,14 @@ void ExecutionBlock::staticAnalysis (ExecutionBlock* super) {
|
|||
sq->getSubquery()->staticAnalysis(s);
|
||||
}
|
||||
v->reset();
|
||||
|
||||
// Just for debugging:
|
||||
/*
|
||||
std::cout << std::endl;
|
||||
StaticAnalysisDebugger debugger;
|
||||
walk(&debugger);
|
||||
std::cout << std::endl;
|
||||
*/
|
||||
}
|
||||
|
||||
int ExecutionBlock::initialize () {
|
||||
|
@ -250,19 +297,20 @@ void ExecutionBlock::inheritRegisters (AqlItemBlock const* src,
|
|||
RegisterId const n = src->getNrRegs();
|
||||
|
||||
for (RegisterId i = 0; i < n; i++) {
|
||||
if (! src->getValue(row, i).isEmpty()) {
|
||||
AqlValue a = src->getValue(row, i).clone();
|
||||
try {
|
||||
dst->setValue(0, i, a);
|
||||
}
|
||||
catch (...) {
|
||||
a.destroy();
|
||||
throw;
|
||||
if (_regsToClear.find(i) == _regsToClear.end()) {
|
||||
if (! src->getValue(row, i).isEmpty()) {
|
||||
AqlValue a = src->getValue(row, i).clone();
|
||||
try {
|
||||
dst->setValue(0, i, a);
|
||||
}
|
||||
catch (...) {
|
||||
a.destroy();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
// copy collection
|
||||
dst->setDocumentCollection(i, src->getDocumentCollection(i));
|
||||
}
|
||||
|
||||
// copy collection
|
||||
dst->setDocumentCollection(i, src->getDocumentCollection(i));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -281,7 +329,14 @@ bool ExecutionBlock::getBlock (size_t atLeast, size_t atMost) {
|
|||
return true;
|
||||
}
|
||||
|
||||
AqlItemBlock* ExecutionBlock::getSome (size_t atLeast, size_t atMost) {
|
||||
AqlItemBlock* ExecutionBlock::getSome(size_t atLeast, size_t atMost) {
|
||||
std::unique_ptr<AqlItemBlock> result(getSomeWithoutRegisterClearout(atLeast, atMost));
|
||||
clearRegisters(result.get());
|
||||
return result.release();
|
||||
}
|
||||
|
||||
AqlItemBlock* ExecutionBlock::getSomeWithoutRegisterClearout (
|
||||
size_t atLeast, size_t atMost) {
|
||||
TRI_ASSERT(0 < atLeast && atLeast <= atMost);
|
||||
size_t skipped = 0;
|
||||
AqlItemBlock* result = nullptr;
|
||||
|
@ -292,6 +347,13 @@ AqlItemBlock* ExecutionBlock::getSome (size_t atLeast, size_t atMost) {
|
|||
return result;
|
||||
}
|
||||
|
||||
void ExecutionBlock::clearRegisters (AqlItemBlock* result) {
|
||||
// Clear out registers not needed later on:
|
||||
if (result != nullptr) {
|
||||
result->clearRegisters(_regsToClear);
|
||||
}
|
||||
}
|
||||
|
||||
size_t ExecutionBlock::skipSome (size_t atLeast, size_t atMost) {
|
||||
TRI_ASSERT(0 < atLeast && atLeast <= atMost);
|
||||
size_t skipped = 0;
|
||||
|
@ -656,6 +718,8 @@ AqlItemBlock* EnumerateCollectionBlock::getSome (size_t atLeast,
|
|||
}
|
||||
}
|
||||
}
|
||||
// Clear out registers no longer needed later:
|
||||
clearRegisters(res.get());
|
||||
return res.release();
|
||||
}
|
||||
|
||||
|
@ -831,6 +895,8 @@ AqlItemBlock* IndexRangeBlock::getSome (size_t atLeast,
|
|||
}
|
||||
}
|
||||
}
|
||||
// Clear out registers no longer needed later:
|
||||
clearRegisters(res.get());
|
||||
return res.release();
|
||||
}
|
||||
|
||||
|
@ -1048,6 +1114,9 @@ AqlItemBlock* EnumerateListBlock::getSome (size_t atLeast, size_t atMost) {
|
|||
}
|
||||
while (res.get() == nullptr);
|
||||
|
||||
// Clear out registers no longer needed later:
|
||||
clearRegisters(res.get());
|
||||
|
||||
return res.release();
|
||||
}
|
||||
|
||||
|
@ -1249,13 +1318,16 @@ void CalculationBlock::doEvaluation (AqlItemBlock* result) {
|
|||
AqlItemBlock* CalculationBlock::getSome (size_t atLeast,
|
||||
size_t atMost) {
|
||||
|
||||
unique_ptr<AqlItemBlock> res(ExecutionBlock::getSome(atLeast, atMost));
|
||||
unique_ptr<AqlItemBlock> res(ExecutionBlock::getSomeWithoutRegisterClearout(
|
||||
atLeast, atMost));
|
||||
|
||||
if (res.get() == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
doEvaluation(res.get());
|
||||
// Clear out registers no longer needed later:
|
||||
clearRegisters(res.get());
|
||||
return res.release();
|
||||
}
|
||||
|
||||
|
@ -1282,7 +1354,8 @@ int SubqueryBlock::initialize () {
|
|||
|
||||
AqlItemBlock* SubqueryBlock::getSome (size_t atLeast,
|
||||
size_t atMost) {
|
||||
unique_ptr<AqlItemBlock> res(ExecutionBlock::getSome(atLeast, atMost));
|
||||
unique_ptr<AqlItemBlock> res(ExecutionBlock::getSomeWithoutRegisterClearout(
|
||||
atLeast, atMost));
|
||||
|
||||
if (res.get() == nullptr) {
|
||||
return nullptr;
|
||||
|
@ -1315,6 +1388,8 @@ AqlItemBlock* SubqueryBlock::getSome (size_t atLeast,
|
|||
throw;
|
||||
}
|
||||
}
|
||||
// Clear out registers no longer needed later:
|
||||
clearRegisters(res.get());
|
||||
return res.release();
|
||||
}
|
||||
|
||||
|
@ -2029,7 +2104,7 @@ int LimitBlock::getOrSkipSome (size_t atLeast,
|
|||
AqlItemBlock* ReturnBlock::getSome (size_t atLeast,
|
||||
size_t atMost) {
|
||||
|
||||
auto res = ExecutionBlock::getSome(atLeast, atMost);
|
||||
auto res = ExecutionBlock::getSomeWithoutRegisterClearout(atLeast, atMost);
|
||||
|
||||
if (res == nullptr) {
|
||||
return res;
|
||||
|
@ -2107,7 +2182,7 @@ AqlItemBlock* ModificationBlock::getSome (size_t atLeast,
|
|||
// loop over input until it is exhausted
|
||||
try {
|
||||
while (true) {
|
||||
auto res = ExecutionBlock::getSome(atLeast, atMost);
|
||||
auto res = ExecutionBlock::getSomeWithoutRegisterClearout(atLeast, atMost);
|
||||
|
||||
if (res == nullptr) {
|
||||
break;
|
||||
|
@ -2707,6 +2782,28 @@ void ExecutionBlock::VarOverview::after (ExecutionBlock *eb) {
|
|||
}
|
||||
eb->_depth = depth;
|
||||
eb->_varOverview = *me;
|
||||
|
||||
// Now find out which registers ought to be erased after this node:
|
||||
auto ep = eb->getPlanNode();
|
||||
if (ep->getType() != ExecutionNode::RETURN) {
|
||||
// ReturnBlocks are special, since they return a single column anyway
|
||||
std::unordered_set<Variable const*> const& varsUsedLater = ep->getVarsUsedLater();
|
||||
std::vector<Variable const*> const& varsUsedHere = ep->getVariablesUsedHere();
|
||||
|
||||
// We need to delete those variables that have been used here but are not
|
||||
// used any more later:
|
||||
std::unordered_set<RegisterId> regsToClear;
|
||||
for (auto v : varsUsedHere) {
|
||||
auto it = varsUsedLater.find(v);
|
||||
if (it == varsUsedLater.end()) {
|
||||
auto it2 = varInfo.find(v->id);
|
||||
TRI_ASSERT(it2 != varInfo.end());
|
||||
RegisterId r = it2->second.registerId;
|
||||
regsToClear.insert(r);
|
||||
}
|
||||
}
|
||||
eb->setRegsToClear(regsToClear);
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
|
|
@ -294,6 +294,27 @@ namespace triagens {
|
|||
|
||||
virtual AqlItemBlock* getSome (size_t atLeast, size_t atMost);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief getSomeWithoutRegisterClearout, same as above, however, this
|
||||
/// is the actual worker which does not clear out registers at the end
|
||||
/// the idea is that somebody who wants to call the generic functionality
|
||||
/// in a derived class but wants to modify the results before the register
|
||||
/// cleanup can use this method, internal use only
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
protected:
|
||||
|
||||
AqlItemBlock* getSomeWithoutRegisterClearout (size_t atLeast, size_t atMost);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief clearRegisters, clears out registers holding values that are no
|
||||
/// longer needed by later nodes
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void clearRegisters (AqlItemBlock* result);
|
||||
|
||||
public:
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief getSome, skips some more items, semantic is as follows: not
|
||||
/// more than atMost items may be skipped. The method tries to
|
||||
|
@ -320,6 +341,14 @@ namespace triagens {
|
|||
return _exeNode;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief set regs to be deleted
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void setRegsToClear (std::unordered_set<RegisterId>& toClear) {
|
||||
_regsToClear = toClear;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -372,6 +401,7 @@ namespace triagens {
|
|||
/// @brief info about variables, filled in by staticAnalysis
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public:
|
||||
std::shared_ptr<VarOverview> _varOverview;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -392,6 +422,16 @@ namespace triagens {
|
|||
|
||||
bool _done;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief the following contains the registers which should be cleared
|
||||
/// just before this node hands on results. This is computed during
|
||||
/// the static analysis for each node using the variable usage in the plan.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public:
|
||||
|
||||
std::unordered_set<RegisterId> _regsToClear;
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- public variables
|
||||
// -----------------------------------------------------------------------------
|
||||
|
|
|
@ -635,7 +635,7 @@ struct SubqueryVarUsageFinder : public WalkerWorker<ExecutionNode> {
|
|||
/// @brief getVariablesUsedHere
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::vector<Variable const*> SubqueryNode::getVariablesUsedHere () {
|
||||
std::vector<Variable const*> SubqueryNode::getVariablesUsedHere () const {
|
||||
SubqueryVarUsageFinder finder;
|
||||
_subquery->walk(&finder);
|
||||
|
||||
|
@ -755,6 +755,50 @@ void AggregateNode::toJsonHelper (triagens::basics::Json& nodes,
|
|||
nodes(json);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief getVariablesUsedHere
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct UserVarFinder : public WalkerWorker<ExecutionNode> {
|
||||
UserVarFinder () {};
|
||||
~UserVarFinder () {};
|
||||
std::vector<Variable const*> userVars;
|
||||
|
||||
bool enterSubquery (ExecutionNode* super, ExecutionNode* sub) {
|
||||
return false;
|
||||
}
|
||||
void before (ExecutionNode* en) {
|
||||
auto vars = en->getVariablesSetHere();
|
||||
for (auto v : vars) {
|
||||
if (v->isUserDefined()) {
|
||||
userVars.push_back(v);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
std::vector<Variable const*> AggregateNode::getVariablesUsedHere () const {
|
||||
std::unordered_set<Variable const*> v;
|
||||
for (auto p : _aggregateVariables) {
|
||||
v.insert(p.second);
|
||||
}
|
||||
if (_outVariable != nullptr) {
|
||||
// Here we have to find all user defined variables in this query
|
||||
// amonst our dependencies:
|
||||
UserVarFinder finder;
|
||||
auto myselfasnonconst = const_cast<AggregateNode*>(this);
|
||||
myselfasnonconst->walk(&finder);
|
||||
for (auto x : finder.userVars) {
|
||||
v.insert(x);
|
||||
}
|
||||
}
|
||||
std::vector<Variable const*> vv;
|
||||
for (auto x : v) {
|
||||
vv.push_back(x);
|
||||
}
|
||||
return vv;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- methods of ReturnNode
|
||||
// -----------------------------------------------------------------------------
|
||||
|
|
|
@ -364,7 +364,7 @@ namespace triagens {
|
|||
/// @brief getVariablesUsedHere
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
virtual std::vector<Variable const*> getVariablesUsedHere () {
|
||||
virtual std::vector<Variable const*> getVariablesUsedHere () const {
|
||||
return std::vector<Variable const*>();
|
||||
}
|
||||
|
||||
|
@ -372,7 +372,7 @@ namespace triagens {
|
|||
/// @brief getVariablesSetHere
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
virtual std::vector<Variable const*> getVariablesSetHere () {
|
||||
virtual std::vector<Variable const*> getVariablesSetHere () const {
|
||||
return std::vector<Variable const*>();
|
||||
}
|
||||
|
||||
|
@ -388,7 +388,7 @@ namespace triagens {
|
|||
/// @brief getVarsUsedLater
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::unordered_set<Variable const*>& getVarsUsedLater () {
|
||||
std::unordered_set<Variable const*> const& getVarsUsedLater () const {
|
||||
TRI_ASSERT(_varUsageValid);
|
||||
return _varsUsedLater;
|
||||
}
|
||||
|
@ -405,7 +405,7 @@ namespace triagens {
|
|||
/// @brief getVarsValid
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::unordered_set<Variable const*>& getVarsValid () {
|
||||
std::unordered_set<Variable const*> const& getVarsValid () const {
|
||||
TRI_ASSERT(_varUsageValid);
|
||||
return _varsValid;
|
||||
}
|
||||
|
@ -648,7 +648,7 @@ namespace triagens {
|
|||
/// @brief getVariablesSetHere
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
virtual std::vector<Variable const*> getVariablesSetHere () {
|
||||
virtual std::vector<Variable const*> getVariablesSetHere () const {
|
||||
std::vector<Variable const*> v;
|
||||
v.push_back(_outVariable);
|
||||
return v;
|
||||
|
@ -770,7 +770,7 @@ namespace triagens {
|
|||
/// @brief getVariablesUsedHere
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
virtual std::vector<Variable const*> getVariablesUsedHere () {
|
||||
virtual std::vector<Variable const*> getVariablesUsedHere () const {
|
||||
std::vector<Variable const*> v;
|
||||
v.push_back(_inVariable);
|
||||
return v;
|
||||
|
@ -780,7 +780,7 @@ namespace triagens {
|
|||
/// @brief getVariablesSetHere
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
virtual std::vector<Variable const*> getVariablesSetHere () {
|
||||
virtual std::vector<Variable const*> getVariablesSetHere () const {
|
||||
std::vector<Variable const*> v;
|
||||
v.push_back(_outVariable);
|
||||
return v;
|
||||
|
@ -885,7 +885,7 @@ namespace triagens {
|
|||
/// @brief getVariablesSetHere
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
virtual std::vector<Variable const*> getVariablesSetHere () {
|
||||
virtual std::vector<Variable const*> getVariablesSetHere () const {
|
||||
std::vector<Variable const*> v;
|
||||
v.push_back(_outVariable);
|
||||
return v;
|
||||
|
@ -1110,7 +1110,7 @@ namespace triagens {
|
|||
/// @brief getVariablesUsedHere
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
virtual std::vector<Variable const*> getVariablesUsedHere () {
|
||||
virtual std::vector<Variable const*> getVariablesUsedHere () const {
|
||||
std::unordered_set<Variable*> vars = _expression->variables();
|
||||
std::vector<Variable const*> v;
|
||||
for (auto vv : vars) {
|
||||
|
@ -1123,7 +1123,7 @@ namespace triagens {
|
|||
/// @brief getVariablesSetHere
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
virtual std::vector<Variable const*> getVariablesSetHere () {
|
||||
virtual std::vector<Variable const*> getVariablesSetHere () const {
|
||||
std::vector<Variable const*> v;
|
||||
v.push_back(_outVariable);
|
||||
return v;
|
||||
|
@ -1248,13 +1248,13 @@ namespace triagens {
|
|||
/// @brief getVariablesUsedHere
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
virtual std::vector<Variable const*> getVariablesUsedHere ();
|
||||
virtual std::vector<Variable const*> getVariablesUsedHere () const;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief getVariablesSetHere
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
virtual std::vector<Variable const*> getVariablesSetHere () {
|
||||
virtual std::vector<Variable const*> getVariablesSetHere () const {
|
||||
std::vector<Variable const*> v;
|
||||
v.push_back(_outVariable);
|
||||
return v;
|
||||
|
@ -1358,7 +1358,7 @@ namespace triagens {
|
|||
/// @brief getVariablesUsedHere
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
virtual std::vector<Variable const*> getVariablesUsedHere () {
|
||||
virtual std::vector<Variable const*> getVariablesUsedHere () const {
|
||||
std::vector<Variable const*> v;
|
||||
v.push_back(_inVariable);
|
||||
return v;
|
||||
|
@ -1442,7 +1442,7 @@ namespace triagens {
|
|||
/// @brief getVariablesUsedHere
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
virtual std::vector<Variable const*> getVariablesUsedHere () {
|
||||
virtual std::vector<Variable const*> getVariablesUsedHere () const {
|
||||
std::vector<Variable const*> v;
|
||||
for (auto p : _elements) {
|
||||
v.push_back(p.first);
|
||||
|
@ -1541,19 +1541,13 @@ namespace triagens {
|
|||
/// @brief getVariablesUsedHere
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
virtual std::vector<Variable const*> getVariablesUsedHere () {
|
||||
std::vector<Variable const*> v;
|
||||
for (auto p : _aggregateVariables) {
|
||||
v.push_back(p.second);
|
||||
}
|
||||
return v;
|
||||
}
|
||||
virtual std::vector<Variable const*> getVariablesUsedHere () const;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief getVariablesSetHere
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
virtual std::vector<Variable const*> getVariablesSetHere () {
|
||||
virtual std::vector<Variable const*> getVariablesSetHere () const {
|
||||
std::vector<Variable const*> v;
|
||||
for (auto p : _aggregateVariables) {
|
||||
v.push_back(p.first);
|
||||
|
@ -1658,7 +1652,7 @@ namespace triagens {
|
|||
/// @brief getVariablesUsedHere
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
virtual std::vector<Variable const*> getVariablesUsedHere () {
|
||||
virtual std::vector<Variable const*> getVariablesUsedHere () const {
|
||||
std::vector<Variable const*> v;
|
||||
v.push_back(_inVariable);
|
||||
return v;
|
||||
|
@ -1815,7 +1809,7 @@ namespace triagens {
|
|||
/// @brief getVariablesUsedHere
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
virtual std::vector<Variable const*> getVariablesUsedHere () {
|
||||
virtual std::vector<Variable const*> getVariablesUsedHere () const {
|
||||
std::vector<Variable const*> v;
|
||||
v.push_back(_inVariable);
|
||||
return v;
|
||||
|
@ -1825,7 +1819,7 @@ namespace triagens {
|
|||
/// @brief getVariablesSetHere
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
virtual std::vector<Variable const*> getVariablesSetHere () {
|
||||
virtual std::vector<Variable const*> getVariablesSetHere () const {
|
||||
std::vector<Variable const*> v;
|
||||
if (_outVariable != nullptr) {
|
||||
v.push_back(_outVariable);
|
||||
|
@ -1927,7 +1921,7 @@ namespace triagens {
|
|||
/// @brief getVariablesUsedHere
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
virtual std::vector<Variable const*> getVariablesUsedHere () {
|
||||
virtual std::vector<Variable const*> getVariablesUsedHere () const {
|
||||
std::vector<Variable const*> v;
|
||||
v.push_back(_inVariable);
|
||||
return v;
|
||||
|
@ -1937,7 +1931,7 @@ namespace triagens {
|
|||
/// @brief getVariablesSetHere
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
virtual std::vector<Variable const*> getVariablesSetHere () {
|
||||
virtual std::vector<Variable const*> getVariablesSetHere () const {
|
||||
std::vector<Variable const*> v;
|
||||
if (_outVariable != nullptr) {
|
||||
v.push_back(_outVariable);
|
||||
|
@ -2042,7 +2036,7 @@ namespace triagens {
|
|||
/// @brief getVariablesUsedHere
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
virtual std::vector<Variable const*> getVariablesUsedHere () {
|
||||
virtual std::vector<Variable const*> getVariablesUsedHere () const {
|
||||
std::vector<Variable const*> v;
|
||||
v.push_back(_inDocVariable);
|
||||
|
||||
|
@ -2056,7 +2050,7 @@ namespace triagens {
|
|||
/// @brief getVariablesSetHere
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
virtual std::vector<Variable const*> getVariablesSetHere () {
|
||||
virtual std::vector<Variable const*> getVariablesSetHere () const {
|
||||
std::vector<Variable const*> v;
|
||||
if (_outVariable != nullptr) {
|
||||
v.push_back(_outVariable);
|
||||
|
@ -2167,7 +2161,7 @@ namespace triagens {
|
|||
/// @brief getVariablesUsedHere
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
virtual std::vector<Variable const*> getVariablesUsedHere () {
|
||||
virtual std::vector<Variable const*> getVariablesUsedHere () const {
|
||||
std::vector<Variable const*> v;
|
||||
v.push_back(_inDocVariable);
|
||||
|
||||
|
@ -2181,7 +2175,7 @@ namespace triagens {
|
|||
/// @brief getVariablesSetHere
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
virtual std::vector<Variable const*> getVariablesSetHere () {
|
||||
virtual std::vector<Variable const*> getVariablesSetHere () const {
|
||||
std::vector<Variable const*> v;
|
||||
if (_outVariable != nullptr) {
|
||||
v.push_back(_outVariable);
|
||||
|
|
|
@ -53,6 +53,7 @@ using JsonHelper = triagens::basics::JsonHelper;
|
|||
ExecutionPlan::ExecutionPlan ()
|
||||
: _ids(),
|
||||
_root(nullptr),
|
||||
_varUsageComputed(false),
|
||||
_nextId(0) {
|
||||
|
||||
}
|
||||
|
@ -997,6 +998,15 @@ void ExecutionPlan::findVarUsage () {
|
|||
VarUsageFinder finder;
|
||||
root()->walk(&finder);
|
||||
_varSetBy = finder._varSetBy;
|
||||
_varUsageComputed = true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief determine if the above are already set
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool ExecutionPlan::varUsageComputed () {
|
||||
return _varUsageComputed;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -1033,6 +1043,7 @@ void ExecutionPlan::unlinkNode (ExecutionNode* node) {
|
|||
node->removeDependency(x);
|
||||
}
|
||||
}
|
||||
_varUsageComputed = false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -1060,6 +1071,7 @@ void ExecutionPlan::replaceNode (ExecutionNode* oldNode,
|
|||
"Could not replace dependencies of an old node.");
|
||||
}
|
||||
}
|
||||
_varUsageComputed = false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -1082,6 +1094,7 @@ void ExecutionPlan::insertDependency (ExecutionNode* oldNode,
|
|||
|
||||
newNode->removeDependencies();
|
||||
newNode->addDependency(oldDeps[0]);
|
||||
_varUsageComputed = false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -1109,7 +1122,9 @@ ExecutionPlan* ExecutionPlan::clone (){
|
|||
plan->_nextId = _nextId;
|
||||
CloneNodeAdder adder(plan);
|
||||
plan->_root->walk(&adder);
|
||||
plan->findVarUsage();
|
||||
// plan->findVarUsage();
|
||||
// Let's not do it here, because supposedly the plan is modified as
|
||||
// the very next thing anyway!
|
||||
return plan;
|
||||
}
|
||||
catch (...) {
|
||||
|
|
|
@ -155,11 +155,17 @@ namespace triagens {
|
|||
void checkLinkage ();
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief determine and set _varsUsedLater in all nodes
|
||||
/// @brief determine and set _varsUsedLater and _valid and _varSetBy
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void findVarUsage ();
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief determine if the above are already set
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool varUsageComputed ();
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief unlinkNodes, note that this does not delete the removed
|
||||
/// nodes and that one cannot remove the root node of the plan.
|
||||
|
@ -358,6 +364,12 @@ namespace triagens {
|
|||
|
||||
std::unordered_map<VariableId, ExecutionNode*> _varSetBy;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief flag to indicate whether the variable usage is computed
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool _varUsageComputed;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief auto-increment sequence for node ids
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -89,7 +89,9 @@ int Optimizer::createPlans (ExecutionPlan* plan) {
|
|||
|
||||
// Find variable usage for all old plans now:
|
||||
for (auto p : oldPlans.list) {
|
||||
p->findVarUsage();
|
||||
if (! p->varUsageComputed()) {
|
||||
p->findVarUsage();
|
||||
}
|
||||
}
|
||||
|
||||
// For all rules:
|
||||
|
|
Loading…
Reference in New Issue