From 4c3ceadeaf01e2553f582a5cf4839a0b0b21fba3 Mon Sep 17 00:00:00 2001 From: jimingquan <6930445+nevermore3@users.noreply.github.com> Date: Sun, 8 Oct 2023 17:59:36 +0800 Subject: [PATCH] each group applies a rule only once --- src/graph/optimizer/OptContext.h | 6 ++++++ src/graph/optimizer/OptGroup.cpp | 9 +++++++++ src/graph/optimizer/Optimizer.cpp | 11 ++++++++++- 3 files changed, 25 insertions(+), 1 deletion(-) diff --git a/src/graph/optimizer/OptContext.h b/src/graph/optimizer/OptContext.h index 87cb213a0e7..6a4c12caf05 100644 --- a/src/graph/optimizer/OptContext.h +++ b/src/graph/optimizer/OptContext.h @@ -9,6 +9,7 @@ #include #include #include +#include #include "common/cpp/helpers.h" @@ -23,6 +24,8 @@ class QueryContext; namespace opt { class OptGroupNode; +class OptGroup; +class Optimizer; class OptContext final : private boost::noncopyable, private cpp::NonMovable { public: @@ -48,12 +51,15 @@ class OptContext final : private boost::noncopyable, private cpp::NonMovable { const OptGroupNode *findOptGroupNodeByPlanNodeId(int64_t planNodeId) const; private: + friend OptGroup; + friend Optimizer; // A global flag to record whether this iteration caused a change to the plan bool changed_{true}; graph::QueryContext *qctx_{nullptr}; // Memo memory management in the Optimizer phase std::unique_ptr objPool_; std::unordered_map planNodeToOptGroupNodeMap_; + std::unordered_set visited_; }; } // namespace opt diff --git a/src/graph/optimizer/OptGroup.cpp b/src/graph/optimizer/OptGroup.cpp index 340881b224d..aea57d0abc2 100644 --- a/src/graph/optimizer/OptGroup.cpp +++ b/src/graph/optimizer/OptGroup.cpp @@ -28,6 +28,9 @@ OptGroup *OptGroup::create(OptContext *ctx) { } void OptGroup::setUnexplored(const OptRule *rule) { + if (!ctx_->visited_.emplace(this).second) { + return; + } auto iter = std::find(exploredRules_.begin(), exploredRules_.end(), rule); if (iter != exploredRules_.end()) { exploredRules_.erase(iter); @@ -100,6 +103,9 @@ Status OptGroup::validate(const OptRule *rule) const { rule->toString().c_str(), groupNodesReferenced_.size()); } + if (!ctx_->visited_.emplace(this).second) { + return Status::OK(); + } for (auto *gn : groupNodes_) { NG_RETURN_IF_ERROR(gn->validate(rule)); if (gn->node()->outputVar() != outputVar_) { @@ -138,6 +144,9 @@ Status OptGroup::explore(const OptRule *rule) { return Status::OK(); } setExplored(rule); + if (!ctx_->visited_.emplace(this).second) { + return Status::OK(); + } // TODO(yee): the opt group maybe in the loop body branch // DCHECK(isRootGroup_ || !groupNodesReferenced_.empty()) diff --git a/src/graph/optimizer/Optimizer.cpp b/src/graph/optimizer/Optimizer.cpp index e37f8f3f300..44a1ebfc3ea 100644 --- a/src/graph/optimizer/Optimizer.cpp +++ b/src/graph/optimizer/Optimizer.cpp @@ -81,8 +81,11 @@ Status Optimizer::doExploration(OptContext *octx, OptGroup *rootGroup) { for (auto rule : ruleSet->rules()) { // Explore until the maximum number of iterations(Rules) is reached NG_RETURN_IF_ERROR(rootGroup->exploreUntilMaxRound(rule)); + octx->visited_.clear(); NG_RETURN_IF_ERROR(rootGroup->validate(rule)); + octx->visited_.clear(); rootGroup->setUnexplored(rule); + octx->visited_.clear(); } } } @@ -226,7 +229,9 @@ Status Optimizer::rewriteArgumentInputVar(PlanNode *root) { Status Optimizer::checkPlanDepth(const PlanNode *root) const { std::queue queue; + std::unordered_set visited; queue.push(root); + visited.emplace(root); size_t depth = 0; while (!queue.empty()) { size_t size = queue.size(); @@ -234,9 +239,13 @@ Status Optimizer::checkPlanDepth(const PlanNode *root) const { const PlanNode *node = queue.front(); queue.pop(); for (size_t j = 0; j < node->numDeps(); j++) { - queue.push(node->dep(j)); + const auto *dep = node->dep(j); + if (visited.emplace(dep).second) { + queue.push(dep); + } } } + ++depth; if (depth > FLAGS_max_plan_depth) { return Status::Error("The depth of plan tree has exceeded the max %lu level",