1
0
Fork 0

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:
Max Neunhoeffer 2014-08-16 00:09:11 +02:00
parent f8cf5dc26d
commit 9e91d9bba3
5 changed files with 143 additions and 3 deletions

View File

@ -709,6 +709,16 @@ namespace triagens {
//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
// -----------------------------------------------------------------------------
@ -1548,6 +1558,28 @@ namespace triagens {
// 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
// -----------------------------------------------------------------------------
@ -1635,6 +1667,28 @@ namespace triagens {
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
// -----------------------------------------------------------------------------

View File

@ -832,6 +832,56 @@ void ExecutionPlan::findVarUsage () {
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
// -----------------------------------------------------------------------------

View File

@ -110,6 +110,13 @@ namespace triagens {
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
// -----------------------------------------------------------------------------
@ -251,7 +258,7 @@ namespace triagens {
std::vector<ExecutionNode*> _nodes;
////////////////////////////////////////////////////////////////////////////////
/// @brief root node of the engine
/// @brief root node of the plan
////////////////////////////////////////////////////////////////////////////////
ExecutionNode* _root;

View File

@ -41,7 +41,8 @@ using namespace triagens::aql;
Optimizer::Optimizer () {
// List all the rules in the system here:
registerRule (relaxRule, 1000);
registerRule (removeUnnecessaryCalc, 999);
// registerRule (removeUnnecessaryCalc, 999);
// deactivated because a test crashes
// Now sort them by pass:
std::stable_sort(_rules.begin(), _rules.end());
@ -65,6 +66,9 @@ int Optimizer::createPlans (ExecutionPlan* plan) {
_plans.clear();
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:
PlanList newPlans;

View File

@ -55,7 +55,32 @@ int triagens::aql::removeUnnecessaryCalc (Optimizer* opt,
bool& keep) {
std::vector<ExecutionNode*> nodes
= 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;
}