mirror of https://gitee.com/bigwinds/arangodb
Finish first optimization rule: remove unnecessary calcs.
So far not activated, because test suite crashes. Need to look into details.
This commit is contained in:
parent
f8cf5dc26d
commit
9e91d9bba3
|
@ -709,6 +709,16 @@ namespace triagens {
|
||||||
//FIXME improve this estimate . . .
|
//FIXME improve this estimate . . .
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief getVariablesSetHere
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
virtual std::vector<Variable const*> getVariablesSetHere () {
|
||||||
|
std::vector<Variable const*> v;
|
||||||
|
v.push_back(_outVariable);
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
// --SECTION-- private variables
|
// --SECTION-- private variables
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
@ -1548,6 +1558,28 @@ namespace triagens {
|
||||||
// TODO: improve this estimate!
|
// TODO: improve this estimate!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief getVariablesUsedHere
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
virtual std::vector<Variable const*> getVariablesUsedHere () {
|
||||||
|
std::vector<Variable const*> v;
|
||||||
|
v.push_back(_inVariable);
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief getVariablesSetHere
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
virtual std::vector<Variable const*> getVariablesSetHere () {
|
||||||
|
std::vector<Variable const*> v;
|
||||||
|
if (_outVariable != nullptr) {
|
||||||
|
v.push_back(_outVariable);
|
||||||
|
}
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
// --SECTION-- private variables
|
// --SECTION-- private variables
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
@ -1635,6 +1667,28 @@ namespace triagens {
|
||||||
return 1000 * _dependencies.at(0)->getCost(); //FIXME change this!
|
return 1000 * _dependencies.at(0)->getCost(); //FIXME change this!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief getVariablesUsedHere
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
virtual std::vector<Variable const*> getVariablesUsedHere () {
|
||||||
|
std::vector<Variable const*> v;
|
||||||
|
v.push_back(_inVariable);
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief getVariablesSetHere
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
virtual std::vector<Variable const*> getVariablesSetHere () {
|
||||||
|
std::vector<Variable const*> v;
|
||||||
|
if (_outVariable != nullptr) {
|
||||||
|
v.push_back(_outVariable);
|
||||||
|
}
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
// --SECTION-- private variables
|
// --SECTION-- private variables
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
|
@ -832,6 +832,56 @@ void ExecutionPlan::findVarUsage () {
|
||||||
root()->walk(&finder);
|
root()->walk(&finder);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief removeNodes
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
struct NodeRemover : public WalkerWorker<ExecutionNode> {
|
||||||
|
|
||||||
|
ExecutionPlan* _plan;
|
||||||
|
std::unordered_set<ExecutionNode*>& _toRemove;
|
||||||
|
std::vector<ExecutionNode*> parents;
|
||||||
|
|
||||||
|
NodeRemover (ExecutionPlan* plan,
|
||||||
|
std::unordered_set<ExecutionNode*>& toRemove)
|
||||||
|
: _plan(plan), _toRemove(toRemove) {
|
||||||
|
}
|
||||||
|
|
||||||
|
~NodeRemover () {
|
||||||
|
};
|
||||||
|
|
||||||
|
void before (ExecutionNode* en) {
|
||||||
|
if (_toRemove.find(en) != _toRemove.end()) {
|
||||||
|
// Remove this node:
|
||||||
|
if (parents.size() == 0) {
|
||||||
|
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL,
|
||||||
|
"Cannot remove root node of plan.");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
auto dep = en->getDependencies();
|
||||||
|
parents.back()->removeDependency(en);
|
||||||
|
if (dep.size() == 1) {
|
||||||
|
parents.back()->addDependency(dep[0]);
|
||||||
|
}
|
||||||
|
else if (dep.size() > 1) {
|
||||||
|
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL,
|
||||||
|
"Cannot remove node with more than one dependency.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
parents.push_back(en);
|
||||||
|
}
|
||||||
|
|
||||||
|
void after (ExecutionNode* en) {
|
||||||
|
parents.pop_back();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void ExecutionPlan::removeNodes (std::unordered_set<ExecutionNode*>& toRemove) {
|
||||||
|
NodeRemover remover(this, toRemove);
|
||||||
|
root()->walk(&remover);
|
||||||
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
// --SECTION-- END-OF-FILE
|
// --SECTION-- END-OF-FILE
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
|
@ -110,6 +110,13 @@ namespace triagens {
|
||||||
|
|
||||||
void findVarUsage ();
|
void findVarUsage ();
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief removeNodes, note that this does not delete the removed
|
||||||
|
/// nodes and that one cannot remove the root node of the plan.
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void removeNodes (std::unordered_set<ExecutionNode*>& toRemove);
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
// --SECTION-- private methods
|
// --SECTION-- private methods
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
@ -251,7 +258,7 @@ namespace triagens {
|
||||||
std::vector<ExecutionNode*> _nodes;
|
std::vector<ExecutionNode*> _nodes;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief root node of the engine
|
/// @brief root node of the plan
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
ExecutionNode* _root;
|
ExecutionNode* _root;
|
||||||
|
|
|
@ -41,7 +41,8 @@ using namespace triagens::aql;
|
||||||
Optimizer::Optimizer () {
|
Optimizer::Optimizer () {
|
||||||
// List all the rules in the system here:
|
// List all the rules in the system here:
|
||||||
registerRule (relaxRule, 1000);
|
registerRule (relaxRule, 1000);
|
||||||
registerRule (removeUnnecessaryCalc, 999);
|
// registerRule (removeUnnecessaryCalc, 999);
|
||||||
|
// deactivated because a test crashes
|
||||||
|
|
||||||
// Now sort them by pass:
|
// Now sort them by pass:
|
||||||
std::stable_sort(_rules.begin(), _rules.end());
|
std::stable_sort(_rules.begin(), _rules.end());
|
||||||
|
@ -65,6 +66,9 @@ int Optimizer::createPlans (ExecutionPlan* plan) {
|
||||||
_plans.clear();
|
_plans.clear();
|
||||||
|
|
||||||
for (int pass = 1; pass <= numberOfPasses; pass++) {
|
for (int pass = 1; pass <= numberOfPasses; pass++) {
|
||||||
|
std::cout << "Entering pass " << pass << " of query optimization..."
|
||||||
|
<< std::endl;
|
||||||
|
|
||||||
// This vector holds the plans we have created in this pass:
|
// This vector holds the plans we have created in this pass:
|
||||||
PlanList newPlans;
|
PlanList newPlans;
|
||||||
|
|
||||||
|
|
|
@ -55,7 +55,32 @@ int triagens::aql::removeUnnecessaryCalc (Optimizer* opt,
|
||||||
bool& keep) {
|
bool& keep) {
|
||||||
std::vector<ExecutionNode*> nodes
|
std::vector<ExecutionNode*> nodes
|
||||||
= plan->findNodesOfType(triagens::aql::ExecutionNode::CALCULATION);
|
= plan->findNodesOfType(triagens::aql::ExecutionNode::CALCULATION);
|
||||||
keep = true;
|
std::unordered_set<ExecutionNode*> toRemove;
|
||||||
|
for (auto n : nodes) {
|
||||||
|
auto nn = static_cast<CalculationNode*>(n);
|
||||||
|
if (! nn->expression()->canThrow()) {
|
||||||
|
// If this node can throw, we must not optimize it away!
|
||||||
|
auto outvar = n->getVariablesSetHere();
|
||||||
|
TRI_ASSERT(outvar.size() == 1);
|
||||||
|
auto varsUsedLater = n->getVarsUsedLater();
|
||||||
|
if (varsUsedLater.find(outvar[0]) == varsUsedLater.end()) {
|
||||||
|
// The variable whose value is calculated here is not used at
|
||||||
|
// all further down the pipeline! We remove the whole
|
||||||
|
// calculation node,
|
||||||
|
toRemove.insert(n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (toRemove.size() > 0) {
|
||||||
|
std::cout << "Removing " << toRemove.size() << " unnecessary "
|
||||||
|
"CalculationNodes..." << std::endl;
|
||||||
|
plan->removeNodes(toRemove);
|
||||||
|
out.push_back(plan);
|
||||||
|
keep = false;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
keep = true;
|
||||||
|
}
|
||||||
return TRI_ERROR_NO_ERROR;
|
return TRI_ERROR_NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue