mirror of https://gitee.com/bigwinds/arangodb
avoid a few dynamic memory allocations in the optimizer (#8393)
This commit is contained in:
parent
6bf276405b
commit
be53ccda97
|
@ -91,11 +91,8 @@ bool ConditionFinder::before(ExecutionNode* en) {
|
|||
}
|
||||
|
||||
case EN::CALCULATION: {
|
||||
auto outvars = en->getVariablesSetHere();
|
||||
TRI_ASSERT(outvars.size() == 1);
|
||||
|
||||
_variableDefinitions.emplace(
|
||||
outvars[0]->id,
|
||||
ExecutionNode::castTo<CalculationNode const*>(en)->outVariable()->id,
|
||||
ExecutionNode::castTo<CalculationNode const*>(en)->expression()->node());
|
||||
TRI_IF_FAILURE("ConditionFinder::variableDefinition") {
|
||||
THROW_ARANGO_EXCEPTION(TRI_ERROR_DEBUG);
|
||||
|
|
|
@ -2533,8 +2533,7 @@ void arangodb::aql::removeRedundantCalculationsRule(Optimizer* opt,
|
|||
continue;
|
||||
}
|
||||
|
||||
auto outvar = n->getVariablesSetHere();
|
||||
TRI_ASSERT(outvar.size() == 1);
|
||||
arangodb::aql::Variable const* outvar = nn->outVariable();
|
||||
|
||||
try {
|
||||
nn->expression()->stringifyIfNotTooLong(&buffer);
|
||||
|
@ -2575,15 +2574,12 @@ void arangodb::aql::removeRedundantCalculationsRule(Optimizer* opt,
|
|||
|
||||
if (isEqual) {
|
||||
// expressions are identical
|
||||
auto outvars = current->getVariablesSetHere();
|
||||
TRI_ASSERT(outvars.size() == 1);
|
||||
|
||||
// check if target variable is already registered as a replacement
|
||||
// this covers the following case:
|
||||
// - replacements is set to B => C
|
||||
// - we're now inserting a replacement A => B
|
||||
// the goal now is to enter a replacement A => C instead of A => B
|
||||
auto target = outvars[0];
|
||||
auto target = ExecutionNode::castTo<CalculationNode const*>(current)->outVariable();
|
||||
while (target != nullptr) {
|
||||
auto it = replacements.find(target->id);
|
||||
|
||||
|
@ -2593,7 +2589,7 @@ void arangodb::aql::removeRedundantCalculationsRule(Optimizer* opt,
|
|||
break;
|
||||
}
|
||||
}
|
||||
replacements.emplace(outvar[0]->id, target);
|
||||
replacements.emplace(outvar->id, target);
|
||||
|
||||
// also check if the insertion enables further shortcuts
|
||||
// this covers the following case:
|
||||
|
@ -2601,7 +2597,7 @@ void arangodb::aql::removeRedundantCalculationsRule(Optimizer* opt,
|
|||
// - we have just inserted a replacement B => C
|
||||
// the goal now is to change the replacement A => B to A => C
|
||||
for (auto it = replacements.begin(); it != replacements.end(); ++it) {
|
||||
if ((*it).second == outvar[0]) {
|
||||
if ((*it).second == outvar) {
|
||||
(*it).second = target;
|
||||
}
|
||||
}
|
||||
|
@ -2649,6 +2645,8 @@ void arangodb::aql::removeUnnecessaryCalculationsRule(Optimizer* opt,
|
|||
arangodb::HashSet<ExecutionNode*> toUnlink;
|
||||
|
||||
for (auto const& n : nodes) {
|
||||
arangodb::aql::Variable const* outVariable = nullptr;
|
||||
|
||||
if (n->getType() == EN::CALCULATION) {
|
||||
auto nn = ExecutionNode::castTo<CalculationNode*>(n);
|
||||
|
||||
|
@ -2656,6 +2654,8 @@ void arangodb::aql::removeUnnecessaryCalculationsRule(Optimizer* opt,
|
|||
// If this node is non-deterministic, we must not optimize it away!
|
||||
continue;
|
||||
}
|
||||
|
||||
outVariable = nn->outVariable();
|
||||
// will remove calculation when we get here
|
||||
} else if (n->getType() == EN::SUBQUERY) {
|
||||
auto nn = ExecutionNode::castTo<SubqueryNode*>(n);
|
||||
|
@ -2670,12 +2670,15 @@ void arangodb::aql::removeUnnecessaryCalculationsRule(Optimizer* opt,
|
|||
continue;
|
||||
}
|
||||
// will remove subquery when we get here
|
||||
outVariable = nn->outVariable();
|
||||
} else {
|
||||
TRI_ASSERT(false);
|
||||
continue;
|
||||
}
|
||||
|
||||
auto outvars = n->getVariablesSetHere();
|
||||
TRI_ASSERT(outvars.size() == 1);
|
||||
TRI_ASSERT(outVariable != nullptr);
|
||||
|
||||
if (!n->isVarUsedLater(outvars[0])) {
|
||||
if (!n->isVarUsedLater(outVariable)) {
|
||||
// The variable whose value is calculated here is not used at
|
||||
// all further down the pipeline! We remove the whole
|
||||
// calculation node,
|
||||
|
@ -2714,7 +2717,7 @@ void arangodb::aql::removeUnnecessaryCalculationsRule(Optimizer* opt,
|
|||
if (!hasCollectWithOutVariable) {
|
||||
// no COLLECT found, now replace
|
||||
std::unordered_map<VariableId, Variable const*> replacements;
|
||||
replacements.emplace(outvars[0]->id,
|
||||
replacements.emplace(outVariable->id,
|
||||
static_cast<Variable const*>(rootNode->getData()));
|
||||
|
||||
RedundantCalculationsReplacer finder(plan->getAst(), replacements);
|
||||
|
@ -2732,7 +2735,7 @@ void arangodb::aql::removeUnnecessaryCalculationsRule(Optimizer* opt,
|
|||
|
||||
while (current != nullptr) {
|
||||
current->getVariablesUsedHere(vars);
|
||||
if (vars.find(outvars[0]) != vars.end()) {
|
||||
if (vars.find(outVariable) != vars.end()) {
|
||||
if (current->getType() == EN::COLLECT) {
|
||||
if (ExecutionNode::castTo<CollectNode const*>(current)->hasOutVariableButNoCount()) {
|
||||
// COLLECT with an INTO variable will collect all variables from
|
||||
|
@ -2771,7 +2774,7 @@ void arangodb::aql::removeUnnecessaryCalculationsRule(Optimizer* opt,
|
|||
TRI_ASSERT(otherExpression != nullptr);
|
||||
|
||||
if (rootNode->type != NODE_TYPE_ATTRIBUTE_ACCESS &&
|
||||
Ast::countReferences(otherExpression->node(), outvars[0]) > 1) {
|
||||
Ast::countReferences(otherExpression->node(), outVariable) > 1) {
|
||||
// used more than once... better give up
|
||||
continue;
|
||||
}
|
||||
|
@ -2789,7 +2792,7 @@ void arangodb::aql::removeUnnecessaryCalculationsRule(Optimizer* opt,
|
|||
}
|
||||
|
||||
TRI_ASSERT(other != nullptr);
|
||||
otherExpression->replaceVariableReference(outvars[0], rootNode);
|
||||
otherExpression->replaceVariableReference(outVariable, rootNode);
|
||||
|
||||
toUnlink.emplace(n);
|
||||
}
|
||||
|
@ -3111,11 +3114,8 @@ struct SortToIndexNode final : public WalkerWorker<ExecutionNode> {
|
|||
return false; // skip. we don't care.
|
||||
|
||||
case EN::CALCULATION: {
|
||||
auto outvars = en->getVariablesSetHere();
|
||||
TRI_ASSERT(outvars.size() == 1);
|
||||
|
||||
_variableDefinitions.emplace(
|
||||
outvars[0]->id,
|
||||
ExecutionNode::castTo<CalculationNode const*>(en)->outVariable()->id,
|
||||
ExecutionNode::castTo<CalculationNode const*>(en)->expression()->node());
|
||||
return false;
|
||||
}
|
||||
|
@ -3810,9 +3810,7 @@ void arangodb::aql::scatterInClusterRule(Optimizer* opt, std::unique_ptr<Executi
|
|||
vocbase = idxNode->vocbase();
|
||||
collection = idxNode->collection();
|
||||
TRI_ASSERT(collection != nullptr);
|
||||
auto outVars = idxNode->getVariablesSetHere();
|
||||
TRI_ASSERT(outVars.size() == 1);
|
||||
Variable const* sortVariable = outVars[0];
|
||||
Variable const* sortVariable = idxNode->outVariable();
|
||||
bool isSortAscending = idxNode->options().ascending;
|
||||
auto allIndexes = idxNode->getIndexes();
|
||||
TRI_ASSERT(!allIndexes.empty());
|
||||
|
@ -4959,8 +4957,7 @@ class RemoveToEnumCollFinder final : public WalkerWorker<ExecutionNode> {
|
|||
auto expr = cn->expression();
|
||||
if (expr->isAttributeAccess()) {
|
||||
// check the variable is the same as the remove variable
|
||||
auto vars = cn->getVariablesSetHere();
|
||||
if (vars.size() != 1 || vars[0] != rn->inVariable()) {
|
||||
if (cn->outVariable() != rn->inVariable()) {
|
||||
break; // abort . . .
|
||||
}
|
||||
// check the remove node's collection is sharded over _key
|
||||
|
@ -5111,7 +5108,7 @@ class RemoveToEnumCollFinder final : public WalkerWorker<ExecutionNode> {
|
|||
auto fn = ExecutionNode::castTo<FilterNode const*>(_lastNode);
|
||||
|
||||
// check these are a Calc-Filter pair
|
||||
if (cn->getVariablesSetHere()[0] != fn->inVariable()) {
|
||||
if (cn->outVariable() != fn->inVariable()) {
|
||||
break; // abort . . .
|
||||
}
|
||||
|
||||
|
@ -5490,9 +5487,9 @@ void arangodb::aql::replaceOrWithInRule(Optimizer* opt, std::unique_ptr<Executio
|
|||
|
||||
auto fn = ExecutionNode::castTo<FilterNode const*>(n);
|
||||
auto cn = ExecutionNode::castTo<CalculationNode*>(dep);
|
||||
auto outVar = cn->getVariablesSetHere();
|
||||
auto outVar = cn->outVariable();
|
||||
|
||||
if (outVar.size() != 1 || outVar[0] != fn->inVariable()) {
|
||||
if (outVar != fn->inVariable()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -5510,7 +5507,7 @@ void arangodb::aql::replaceOrWithInRule(Optimizer* opt, std::unique_ptr<Executio
|
|||
THROW_ARANGO_EXCEPTION(TRI_ERROR_DEBUG);
|
||||
}
|
||||
|
||||
newNode = new CalculationNode(plan.get(), plan->nextId(), expr, outVar[0]);
|
||||
newNode = new CalculationNode(plan.get(), plan->nextId(), expr, outVar);
|
||||
} catch (...) {
|
||||
delete expr;
|
||||
throw;
|
||||
|
@ -5664,9 +5661,9 @@ void arangodb::aql::removeRedundantOrRule(Optimizer* opt,
|
|||
|
||||
auto fn = ExecutionNode::castTo<FilterNode const*>(n);
|
||||
auto cn = ExecutionNode::castTo<CalculationNode*>(dep);
|
||||
auto outVar = cn->getVariablesSetHere();
|
||||
auto outVar = cn->outVariable();
|
||||
|
||||
if (outVar.size() != 1 || outVar[0] != fn->inVariable()) {
|
||||
if (outVar != fn->inVariable()) {
|
||||
continue;
|
||||
}
|
||||
if (cn->expression()->node()->type != NODE_TYPE_OPERATOR_BINARY_OR) {
|
||||
|
@ -5681,7 +5678,7 @@ void arangodb::aql::removeRedundantOrRule(Optimizer* opt,
|
|||
Expression* expr = new Expression(plan.get(), plan->getAst(), astNode);
|
||||
|
||||
try {
|
||||
newNode = new CalculationNode(plan.get(), plan->nextId(), expr, outVar[0]);
|
||||
newNode = new CalculationNode(plan.get(), plan->nextId(), expr, outVar);
|
||||
} catch (...) {
|
||||
delete expr;
|
||||
throw;
|
||||
|
|
Loading…
Reference in New Issue