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;
|
_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
|
/// @brief slice/clone, this does a deep copy of all entries
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
|
@ -239,6 +239,13 @@ namespace triagens {
|
||||||
|
|
||||||
void shrink (size_t nrItems);
|
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
|
/// @brief slice/clone, this does a deep copy of all entries
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
|
@ -194,6 +194,45 @@ void ExecutionBlock::walk (WalkerWorker<ExecutionBlock>* worker) {
|
||||||
/// @brief static analysis
|
/// @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) {
|
void ExecutionBlock::staticAnalysis (ExecutionBlock* super) {
|
||||||
// The super is only for the case of subqueries.
|
// The super is only for the case of subqueries.
|
||||||
shared_ptr<VarOverview> v;
|
shared_ptr<VarOverview> v;
|
||||||
|
@ -211,6 +250,14 @@ void ExecutionBlock::staticAnalysis (ExecutionBlock* super) {
|
||||||
sq->getSubquery()->staticAnalysis(s);
|
sq->getSubquery()->staticAnalysis(s);
|
||||||
}
|
}
|
||||||
v->reset();
|
v->reset();
|
||||||
|
|
||||||
|
// Just for debugging:
|
||||||
|
/*
|
||||||
|
std::cout << std::endl;
|
||||||
|
StaticAnalysisDebugger debugger;
|
||||||
|
walk(&debugger);
|
||||||
|
std::cout << std::endl;
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
int ExecutionBlock::initialize () {
|
int ExecutionBlock::initialize () {
|
||||||
|
@ -250,19 +297,20 @@ void ExecutionBlock::inheritRegisters (AqlItemBlock const* src,
|
||||||
RegisterId const n = src->getNrRegs();
|
RegisterId const n = src->getNrRegs();
|
||||||
|
|
||||||
for (RegisterId i = 0; i < n; i++) {
|
for (RegisterId i = 0; i < n; i++) {
|
||||||
if (! src->getValue(row, i).isEmpty()) {
|
if (_regsToClear.find(i) == _regsToClear.end()) {
|
||||||
AqlValue a = src->getValue(row, i).clone();
|
if (! src->getValue(row, i).isEmpty()) {
|
||||||
try {
|
AqlValue a = src->getValue(row, i).clone();
|
||||||
dst->setValue(0, i, a);
|
try {
|
||||||
}
|
dst->setValue(0, i, a);
|
||||||
catch (...) {
|
}
|
||||||
a.destroy();
|
catch (...) {
|
||||||
throw;
|
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;
|
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);
|
TRI_ASSERT(0 < atLeast && atLeast <= atMost);
|
||||||
size_t skipped = 0;
|
size_t skipped = 0;
|
||||||
AqlItemBlock* result = nullptr;
|
AqlItemBlock* result = nullptr;
|
||||||
|
@ -292,6 +347,13 @@ AqlItemBlock* ExecutionBlock::getSome (size_t atLeast, size_t atMost) {
|
||||||
return result;
|
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) {
|
size_t ExecutionBlock::skipSome (size_t atLeast, size_t atMost) {
|
||||||
TRI_ASSERT(0 < atLeast && atLeast <= atMost);
|
TRI_ASSERT(0 < atLeast && atLeast <= atMost);
|
||||||
size_t skipped = 0;
|
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();
|
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();
|
return res.release();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1048,6 +1114,9 @@ AqlItemBlock* EnumerateListBlock::getSome (size_t atLeast, size_t atMost) {
|
||||||
}
|
}
|
||||||
while (res.get() == nullptr);
|
while (res.get() == nullptr);
|
||||||
|
|
||||||
|
// Clear out registers no longer needed later:
|
||||||
|
clearRegisters(res.get());
|
||||||
|
|
||||||
return res.release();
|
return res.release();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1249,13 +1318,16 @@ void CalculationBlock::doEvaluation (AqlItemBlock* result) {
|
||||||
AqlItemBlock* CalculationBlock::getSome (size_t atLeast,
|
AqlItemBlock* CalculationBlock::getSome (size_t atLeast,
|
||||||
size_t atMost) {
|
size_t atMost) {
|
||||||
|
|
||||||
unique_ptr<AqlItemBlock> res(ExecutionBlock::getSome(atLeast, atMost));
|
unique_ptr<AqlItemBlock> res(ExecutionBlock::getSomeWithoutRegisterClearout(
|
||||||
|
atLeast, atMost));
|
||||||
|
|
||||||
if (res.get() == nullptr) {
|
if (res.get() == nullptr) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
doEvaluation(res.get());
|
doEvaluation(res.get());
|
||||||
|
// Clear out registers no longer needed later:
|
||||||
|
clearRegisters(res.get());
|
||||||
return res.release();
|
return res.release();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1282,7 +1354,8 @@ int SubqueryBlock::initialize () {
|
||||||
|
|
||||||
AqlItemBlock* SubqueryBlock::getSome (size_t atLeast,
|
AqlItemBlock* SubqueryBlock::getSome (size_t atLeast,
|
||||||
size_t atMost) {
|
size_t atMost) {
|
||||||
unique_ptr<AqlItemBlock> res(ExecutionBlock::getSome(atLeast, atMost));
|
unique_ptr<AqlItemBlock> res(ExecutionBlock::getSomeWithoutRegisterClearout(
|
||||||
|
atLeast, atMost));
|
||||||
|
|
||||||
if (res.get() == nullptr) {
|
if (res.get() == nullptr) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -1315,6 +1388,8 @@ AqlItemBlock* SubqueryBlock::getSome (size_t atLeast,
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Clear out registers no longer needed later:
|
||||||
|
clearRegisters(res.get());
|
||||||
return res.release();
|
return res.release();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2029,7 +2104,7 @@ int LimitBlock::getOrSkipSome (size_t atLeast,
|
||||||
AqlItemBlock* ReturnBlock::getSome (size_t atLeast,
|
AqlItemBlock* ReturnBlock::getSome (size_t atLeast,
|
||||||
size_t atMost) {
|
size_t atMost) {
|
||||||
|
|
||||||
auto res = ExecutionBlock::getSome(atLeast, atMost);
|
auto res = ExecutionBlock::getSomeWithoutRegisterClearout(atLeast, atMost);
|
||||||
|
|
||||||
if (res == nullptr) {
|
if (res == nullptr) {
|
||||||
return res;
|
return res;
|
||||||
|
@ -2107,7 +2182,7 @@ AqlItemBlock* ModificationBlock::getSome (size_t atLeast,
|
||||||
// loop over input until it is exhausted
|
// loop over input until it is exhausted
|
||||||
try {
|
try {
|
||||||
while (true) {
|
while (true) {
|
||||||
auto res = ExecutionBlock::getSome(atLeast, atMost);
|
auto res = ExecutionBlock::getSomeWithoutRegisterClearout(atLeast, atMost);
|
||||||
|
|
||||||
if (res == nullptr) {
|
if (res == nullptr) {
|
||||||
break;
|
break;
|
||||||
|
@ -2707,6 +2782,28 @@ void ExecutionBlock::VarOverview::after (ExecutionBlock *eb) {
|
||||||
}
|
}
|
||||||
eb->_depth = depth;
|
eb->_depth = depth;
|
||||||
eb->_varOverview = *me;
|
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);
|
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
|
/// @brief getSome, skips some more items, semantic is as follows: not
|
||||||
/// more than atMost items may be skipped. The method tries to
|
/// more than atMost items may be skipped. The method tries to
|
||||||
|
@ -320,6 +341,14 @@ namespace triagens {
|
||||||
return _exeNode;
|
return _exeNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief set regs to be deleted
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void setRegsToClear (std::unordered_set<RegisterId>& toClear) {
|
||||||
|
_regsToClear = toClear;
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -372,6 +401,7 @@ namespace triagens {
|
||||||
/// @brief info about variables, filled in by staticAnalysis
|
/// @brief info about variables, filled in by staticAnalysis
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
public:
|
||||||
std::shared_ptr<VarOverview> _varOverview;
|
std::shared_ptr<VarOverview> _varOverview;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -392,6 +422,16 @@ namespace triagens {
|
||||||
|
|
||||||
bool _done;
|
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
|
// --SECTION-- public variables
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
|
@ -635,7 +635,7 @@ struct SubqueryVarUsageFinder : public WalkerWorker<ExecutionNode> {
|
||||||
/// @brief getVariablesUsedHere
|
/// @brief getVariablesUsedHere
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
std::vector<Variable const*> SubqueryNode::getVariablesUsedHere () {
|
std::vector<Variable const*> SubqueryNode::getVariablesUsedHere () const {
|
||||||
SubqueryVarUsageFinder finder;
|
SubqueryVarUsageFinder finder;
|
||||||
_subquery->walk(&finder);
|
_subquery->walk(&finder);
|
||||||
|
|
||||||
|
@ -755,6 +755,50 @@ void AggregateNode::toJsonHelper (triagens::basics::Json& nodes,
|
||||||
nodes(json);
|
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
|
// --SECTION-- methods of ReturnNode
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
|
@ -364,7 +364,7 @@ namespace triagens {
|
||||||
/// @brief getVariablesUsedHere
|
/// @brief getVariablesUsedHere
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
virtual std::vector<Variable const*> getVariablesUsedHere () {
|
virtual std::vector<Variable const*> getVariablesUsedHere () const {
|
||||||
return std::vector<Variable const*>();
|
return std::vector<Variable const*>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -372,7 +372,7 @@ namespace triagens {
|
||||||
/// @brief getVariablesSetHere
|
/// @brief getVariablesSetHere
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
virtual std::vector<Variable const*> getVariablesSetHere () {
|
virtual std::vector<Variable const*> getVariablesSetHere () const {
|
||||||
return std::vector<Variable const*>();
|
return std::vector<Variable const*>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -388,7 +388,7 @@ namespace triagens {
|
||||||
/// @brief getVarsUsedLater
|
/// @brief getVarsUsedLater
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
std::unordered_set<Variable const*>& getVarsUsedLater () {
|
std::unordered_set<Variable const*> const& getVarsUsedLater () const {
|
||||||
TRI_ASSERT(_varUsageValid);
|
TRI_ASSERT(_varUsageValid);
|
||||||
return _varsUsedLater;
|
return _varsUsedLater;
|
||||||
}
|
}
|
||||||
|
@ -405,7 +405,7 @@ namespace triagens {
|
||||||
/// @brief getVarsValid
|
/// @brief getVarsValid
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
std::unordered_set<Variable const*>& getVarsValid () {
|
std::unordered_set<Variable const*> const& getVarsValid () const {
|
||||||
TRI_ASSERT(_varUsageValid);
|
TRI_ASSERT(_varUsageValid);
|
||||||
return _varsValid;
|
return _varsValid;
|
||||||
}
|
}
|
||||||
|
@ -648,7 +648,7 @@ namespace triagens {
|
||||||
/// @brief getVariablesSetHere
|
/// @brief getVariablesSetHere
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
virtual std::vector<Variable const*> getVariablesSetHere () {
|
virtual std::vector<Variable const*> getVariablesSetHere () const {
|
||||||
std::vector<Variable const*> v;
|
std::vector<Variable const*> v;
|
||||||
v.push_back(_outVariable);
|
v.push_back(_outVariable);
|
||||||
return v;
|
return v;
|
||||||
|
@ -770,7 +770,7 @@ namespace triagens {
|
||||||
/// @brief getVariablesUsedHere
|
/// @brief getVariablesUsedHere
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
virtual std::vector<Variable const*> getVariablesUsedHere () {
|
virtual std::vector<Variable const*> getVariablesUsedHere () const {
|
||||||
std::vector<Variable const*> v;
|
std::vector<Variable const*> v;
|
||||||
v.push_back(_inVariable);
|
v.push_back(_inVariable);
|
||||||
return v;
|
return v;
|
||||||
|
@ -780,7 +780,7 @@ namespace triagens {
|
||||||
/// @brief getVariablesSetHere
|
/// @brief getVariablesSetHere
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
virtual std::vector<Variable const*> getVariablesSetHere () {
|
virtual std::vector<Variable const*> getVariablesSetHere () const {
|
||||||
std::vector<Variable const*> v;
|
std::vector<Variable const*> v;
|
||||||
v.push_back(_outVariable);
|
v.push_back(_outVariable);
|
||||||
return v;
|
return v;
|
||||||
|
@ -885,7 +885,7 @@ namespace triagens {
|
||||||
/// @brief getVariablesSetHere
|
/// @brief getVariablesSetHere
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
virtual std::vector<Variable const*> getVariablesSetHere () {
|
virtual std::vector<Variable const*> getVariablesSetHere () const {
|
||||||
std::vector<Variable const*> v;
|
std::vector<Variable const*> v;
|
||||||
v.push_back(_outVariable);
|
v.push_back(_outVariable);
|
||||||
return v;
|
return v;
|
||||||
|
@ -1110,7 +1110,7 @@ namespace triagens {
|
||||||
/// @brief getVariablesUsedHere
|
/// @brief getVariablesUsedHere
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
virtual std::vector<Variable const*> getVariablesUsedHere () {
|
virtual std::vector<Variable const*> getVariablesUsedHere () const {
|
||||||
std::unordered_set<Variable*> vars = _expression->variables();
|
std::unordered_set<Variable*> vars = _expression->variables();
|
||||||
std::vector<Variable const*> v;
|
std::vector<Variable const*> v;
|
||||||
for (auto vv : vars) {
|
for (auto vv : vars) {
|
||||||
|
@ -1123,7 +1123,7 @@ namespace triagens {
|
||||||
/// @brief getVariablesSetHere
|
/// @brief getVariablesSetHere
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
virtual std::vector<Variable const*> getVariablesSetHere () {
|
virtual std::vector<Variable const*> getVariablesSetHere () const {
|
||||||
std::vector<Variable const*> v;
|
std::vector<Variable const*> v;
|
||||||
v.push_back(_outVariable);
|
v.push_back(_outVariable);
|
||||||
return v;
|
return v;
|
||||||
|
@ -1248,13 +1248,13 @@ namespace triagens {
|
||||||
/// @brief getVariablesUsedHere
|
/// @brief getVariablesUsedHere
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
virtual std::vector<Variable const*> getVariablesUsedHere ();
|
virtual std::vector<Variable const*> getVariablesUsedHere () const;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief getVariablesSetHere
|
/// @brief getVariablesSetHere
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
virtual std::vector<Variable const*> getVariablesSetHere () {
|
virtual std::vector<Variable const*> getVariablesSetHere () const {
|
||||||
std::vector<Variable const*> v;
|
std::vector<Variable const*> v;
|
||||||
v.push_back(_outVariable);
|
v.push_back(_outVariable);
|
||||||
return v;
|
return v;
|
||||||
|
@ -1358,7 +1358,7 @@ namespace triagens {
|
||||||
/// @brief getVariablesUsedHere
|
/// @brief getVariablesUsedHere
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
virtual std::vector<Variable const*> getVariablesUsedHere () {
|
virtual std::vector<Variable const*> getVariablesUsedHere () const {
|
||||||
std::vector<Variable const*> v;
|
std::vector<Variable const*> v;
|
||||||
v.push_back(_inVariable);
|
v.push_back(_inVariable);
|
||||||
return v;
|
return v;
|
||||||
|
@ -1442,7 +1442,7 @@ namespace triagens {
|
||||||
/// @brief getVariablesUsedHere
|
/// @brief getVariablesUsedHere
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
virtual std::vector<Variable const*> getVariablesUsedHere () {
|
virtual std::vector<Variable const*> getVariablesUsedHere () const {
|
||||||
std::vector<Variable const*> v;
|
std::vector<Variable const*> v;
|
||||||
for (auto p : _elements) {
|
for (auto p : _elements) {
|
||||||
v.push_back(p.first);
|
v.push_back(p.first);
|
||||||
|
@ -1541,19 +1541,13 @@ namespace triagens {
|
||||||
/// @brief getVariablesUsedHere
|
/// @brief getVariablesUsedHere
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
virtual std::vector<Variable const*> getVariablesUsedHere () {
|
virtual std::vector<Variable const*> getVariablesUsedHere () const;
|
||||||
std::vector<Variable const*> v;
|
|
||||||
for (auto p : _aggregateVariables) {
|
|
||||||
v.push_back(p.second);
|
|
||||||
}
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief getVariablesSetHere
|
/// @brief getVariablesSetHere
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
virtual std::vector<Variable const*> getVariablesSetHere () {
|
virtual std::vector<Variable const*> getVariablesSetHere () const {
|
||||||
std::vector<Variable const*> v;
|
std::vector<Variable const*> v;
|
||||||
for (auto p : _aggregateVariables) {
|
for (auto p : _aggregateVariables) {
|
||||||
v.push_back(p.first);
|
v.push_back(p.first);
|
||||||
|
@ -1658,7 +1652,7 @@ namespace triagens {
|
||||||
/// @brief getVariablesUsedHere
|
/// @brief getVariablesUsedHere
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
virtual std::vector<Variable const*> getVariablesUsedHere () {
|
virtual std::vector<Variable const*> getVariablesUsedHere () const {
|
||||||
std::vector<Variable const*> v;
|
std::vector<Variable const*> v;
|
||||||
v.push_back(_inVariable);
|
v.push_back(_inVariable);
|
||||||
return v;
|
return v;
|
||||||
|
@ -1815,7 +1809,7 @@ namespace triagens {
|
||||||
/// @brief getVariablesUsedHere
|
/// @brief getVariablesUsedHere
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
virtual std::vector<Variable const*> getVariablesUsedHere () {
|
virtual std::vector<Variable const*> getVariablesUsedHere () const {
|
||||||
std::vector<Variable const*> v;
|
std::vector<Variable const*> v;
|
||||||
v.push_back(_inVariable);
|
v.push_back(_inVariable);
|
||||||
return v;
|
return v;
|
||||||
|
@ -1825,7 +1819,7 @@ namespace triagens {
|
||||||
/// @brief getVariablesSetHere
|
/// @brief getVariablesSetHere
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
virtual std::vector<Variable const*> getVariablesSetHere () {
|
virtual std::vector<Variable const*> getVariablesSetHere () const {
|
||||||
std::vector<Variable const*> v;
|
std::vector<Variable const*> v;
|
||||||
if (_outVariable != nullptr) {
|
if (_outVariable != nullptr) {
|
||||||
v.push_back(_outVariable);
|
v.push_back(_outVariable);
|
||||||
|
@ -1927,7 +1921,7 @@ namespace triagens {
|
||||||
/// @brief getVariablesUsedHere
|
/// @brief getVariablesUsedHere
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
virtual std::vector<Variable const*> getVariablesUsedHere () {
|
virtual std::vector<Variable const*> getVariablesUsedHere () const {
|
||||||
std::vector<Variable const*> v;
|
std::vector<Variable const*> v;
|
||||||
v.push_back(_inVariable);
|
v.push_back(_inVariable);
|
||||||
return v;
|
return v;
|
||||||
|
@ -1937,7 +1931,7 @@ namespace triagens {
|
||||||
/// @brief getVariablesSetHere
|
/// @brief getVariablesSetHere
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
virtual std::vector<Variable const*> getVariablesSetHere () {
|
virtual std::vector<Variable const*> getVariablesSetHere () const {
|
||||||
std::vector<Variable const*> v;
|
std::vector<Variable const*> v;
|
||||||
if (_outVariable != nullptr) {
|
if (_outVariable != nullptr) {
|
||||||
v.push_back(_outVariable);
|
v.push_back(_outVariable);
|
||||||
|
@ -2042,7 +2036,7 @@ namespace triagens {
|
||||||
/// @brief getVariablesUsedHere
|
/// @brief getVariablesUsedHere
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
virtual std::vector<Variable const*> getVariablesUsedHere () {
|
virtual std::vector<Variable const*> getVariablesUsedHere () const {
|
||||||
std::vector<Variable const*> v;
|
std::vector<Variable const*> v;
|
||||||
v.push_back(_inDocVariable);
|
v.push_back(_inDocVariable);
|
||||||
|
|
||||||
|
@ -2056,7 +2050,7 @@ namespace triagens {
|
||||||
/// @brief getVariablesSetHere
|
/// @brief getVariablesSetHere
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
virtual std::vector<Variable const*> getVariablesSetHere () {
|
virtual std::vector<Variable const*> getVariablesSetHere () const {
|
||||||
std::vector<Variable const*> v;
|
std::vector<Variable const*> v;
|
||||||
if (_outVariable != nullptr) {
|
if (_outVariable != nullptr) {
|
||||||
v.push_back(_outVariable);
|
v.push_back(_outVariable);
|
||||||
|
@ -2167,7 +2161,7 @@ namespace triagens {
|
||||||
/// @brief getVariablesUsedHere
|
/// @brief getVariablesUsedHere
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
virtual std::vector<Variable const*> getVariablesUsedHere () {
|
virtual std::vector<Variable const*> getVariablesUsedHere () const {
|
||||||
std::vector<Variable const*> v;
|
std::vector<Variable const*> v;
|
||||||
v.push_back(_inDocVariable);
|
v.push_back(_inDocVariable);
|
||||||
|
|
||||||
|
@ -2181,7 +2175,7 @@ namespace triagens {
|
||||||
/// @brief getVariablesSetHere
|
/// @brief getVariablesSetHere
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
virtual std::vector<Variable const*> getVariablesSetHere () {
|
virtual std::vector<Variable const*> getVariablesSetHere () const {
|
||||||
std::vector<Variable const*> v;
|
std::vector<Variable const*> v;
|
||||||
if (_outVariable != nullptr) {
|
if (_outVariable != nullptr) {
|
||||||
v.push_back(_outVariable);
|
v.push_back(_outVariable);
|
||||||
|
|
|
@ -53,6 +53,7 @@ using JsonHelper = triagens::basics::JsonHelper;
|
||||||
ExecutionPlan::ExecutionPlan ()
|
ExecutionPlan::ExecutionPlan ()
|
||||||
: _ids(),
|
: _ids(),
|
||||||
_root(nullptr),
|
_root(nullptr),
|
||||||
|
_varUsageComputed(false),
|
||||||
_nextId(0) {
|
_nextId(0) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -997,6 +998,15 @@ void ExecutionPlan::findVarUsage () {
|
||||||
VarUsageFinder finder;
|
VarUsageFinder finder;
|
||||||
root()->walk(&finder);
|
root()->walk(&finder);
|
||||||
_varSetBy = finder._varSetBy;
|
_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);
|
node->removeDependency(x);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
_varUsageComputed = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -1060,6 +1071,7 @@ void ExecutionPlan::replaceNode (ExecutionNode* oldNode,
|
||||||
"Could not replace dependencies of an old node.");
|
"Could not replace dependencies of an old node.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
_varUsageComputed = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -1082,6 +1094,7 @@ void ExecutionPlan::insertDependency (ExecutionNode* oldNode,
|
||||||
|
|
||||||
newNode->removeDependencies();
|
newNode->removeDependencies();
|
||||||
newNode->addDependency(oldDeps[0]);
|
newNode->addDependency(oldDeps[0]);
|
||||||
|
_varUsageComputed = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -1109,7 +1122,9 @@ ExecutionPlan* ExecutionPlan::clone (){
|
||||||
plan->_nextId = _nextId;
|
plan->_nextId = _nextId;
|
||||||
CloneNodeAdder adder(plan);
|
CloneNodeAdder adder(plan);
|
||||||
plan->_root->walk(&adder);
|
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;
|
return plan;
|
||||||
}
|
}
|
||||||
catch (...) {
|
catch (...) {
|
||||||
|
|
|
@ -155,11 +155,17 @@ namespace triagens {
|
||||||
void checkLinkage ();
|
void checkLinkage ();
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief determine and set _varsUsedLater in all nodes
|
/// @brief determine and set _varsUsedLater and _valid and _varSetBy
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void findVarUsage ();
|
void findVarUsage ();
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief determine if the above are already set
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
bool varUsageComputed ();
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief unlinkNodes, note that this does not delete the removed
|
/// @brief unlinkNodes, note that this does not delete the removed
|
||||||
/// nodes and that one cannot remove the root node of the plan.
|
/// nodes and that one cannot remove the root node of the plan.
|
||||||
|
@ -358,6 +364,12 @@ namespace triagens {
|
||||||
|
|
||||||
std::unordered_map<VariableId, ExecutionNode*> _varSetBy;
|
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
|
/// @brief auto-increment sequence for node ids
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
|
@ -89,7 +89,9 @@ int Optimizer::createPlans (ExecutionPlan* plan) {
|
||||||
|
|
||||||
// Find variable usage for all old plans now:
|
// Find variable usage for all old plans now:
|
||||||
for (auto p : oldPlans.list) {
|
for (auto p : oldPlans.list) {
|
||||||
p->findVarUsage();
|
if (! p->varUsageComputed()) {
|
||||||
|
p->findVarUsage();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// For all rules:
|
// For all rules:
|
||||||
|
|
Loading…
Reference in New Issue