This is an automated email from the ASF dual-hosted git repository.

yiguolei pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/doris.git


The following commit(s) were added to refs/heads/master by this push:
     new a6d64c6b25f [refine](profilev2) format profilev2 (#25963)
a6d64c6b25f is described below

commit a6d64c6b25f27537b8e140e26d1e3d8c684e1553
Author: Mryange <[email protected]>
AuthorDate: Fri Oct 27 14:26:38 2023 +0800

    [refine](profilev2) format profilev2 (#25963)
---
 be/src/pipeline/exec/exchange_sink_operator.cpp    |   8 ++
 be/src/pipeline/exec/exchange_sink_operator.h      |   1 +
 .../org/apache/doris/common/profile/Profile.java   |   2 +-
 .../org/apache/doris/common/util/AggCounter.java   |  66 +++++++++
 .../java/org/apache/doris/common/util/Counter.java |  26 ++--
 .../apache/doris/common/util/RuntimeProfile.java   | 154 +++++++++++++++++++--
 .../org/apache/doris/planner/PlanFragment.java     |   8 ++
 .../java/org/apache/doris/planner/PlanNode.java    |  22 +++
 .../java/org/apache/doris/planner/Planner.java     |  11 ++
 9 files changed, 278 insertions(+), 20 deletions(-)

diff --git a/be/src/pipeline/exec/exchange_sink_operator.cpp 
b/be/src/pipeline/exec/exchange_sink_operator.cpp
index 0988052a981..0ca38d81c13 100644
--- a/be/src/pipeline/exec/exchange_sink_operator.cpp
+++ b/be/src/pipeline/exec/exchange_sink_operator.cpp
@@ -235,6 +235,14 @@ Status ExchangeSinkLocalState::open(RuntimeState* state) {
     return Status::OK();
 }
 
+std::string ExchangeSinkLocalState::id_name() {
+    std::string name = " (id=" + std::to_string(_parent->node_id());
+    auto& p = _parent->cast<ExchangeSinkOperatorX>();
+    name += ",dest_id=" + std::to_string(p._dest_node_id);
+    name += ")";
+    return name;
+}
+
 segment_v2::CompressionTypePB& ExchangeSinkLocalState::compression_type() {
     return _parent->cast<ExchangeSinkOperatorX>()._compression_type;
 }
diff --git a/be/src/pipeline/exec/exchange_sink_operator.h 
b/be/src/pipeline/exec/exchange_sink_operator.h
index 69fa4da4be4..05fa799e5cf 100644
--- a/be/src/pipeline/exec/exchange_sink_operator.h
+++ b/be/src/pipeline/exec/exchange_sink_operator.h
@@ -159,6 +159,7 @@ public:
 
     [[nodiscard]] int sender_id() const { return _sender_id; }
 
+    std::string id_name() override;
     segment_v2::CompressionTypePB& compression_type();
 
     std::vector<vectorized::PipChannel<ExchangeSinkLocalState>*> channels;
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/common/profile/Profile.java 
b/fe/fe-core/src/main/java/org/apache/doris/common/profile/Profile.java
index e75082ddb42..2d4424177a3 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/common/profile/Profile.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/common/profile/Profile.java
@@ -72,7 +72,7 @@ public class Profile {
             executionProfile.update(startTime, isFinished);
         }
         rootProfile.computeTimeInProfile();
-        rootProfile.setPlaner(planner);
+        rootProfile.setFragmentPlanInfo(planner);
         rootProfile.setProfileLevel(profileLevel);
         rootProfile.setIsPipelineX(isPipelineX);
         ProfileManager.getInstance().pushProfile(rootProfile);
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/common/util/AggCounter.java 
b/fe/fe-core/src/main/java/org/apache/doris/common/util/AggCounter.java
new file mode 100644
index 00000000000..ed8f91533fb
--- /dev/null
+++ b/fe/fe-core/src/main/java/org/apache/doris/common/util/AggCounter.java
@@ -0,0 +1,66 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package org.apache.doris.common.util;
+
+import java.util.LinkedList;
+
+// Counter means indicators field. The counter's name is key, the counter 
itself is value.
+public class AggCounter extends Counter {
+    Counter max;
+    Counter sum;
+    Counter min;
+    int number;
+
+    public AggCounter(org.apache.doris.thrift.TUnit type, long value) {
+        super(type, value);
+        max = new Counter(type, value);
+        sum = new Counter(type, value);
+        min = new Counter(type, value);
+        number = 1;
+    }
+
+    public void addCounter(Counter counter) {
+        max.maxValue(counter);
+        sum.addValue(counter);
+        min.minValue(counter);
+        number++;
+    }
+
+    public void addCounters(LinkedList<Counter> rhsCounter) {
+        for (Counter counter : rhsCounter) {
+            addCounter(counter);
+        }
+    }
+
+    public String print() {
+        if (isTimeType()) {
+            Counter avg = new Counter(sum.getType(), sum.getValue());
+            avg.divValue(number);
+            String infoString = RuntimeProfile.AVG_TIME_PRE
+                    + RuntimeProfile.printCounter(avg.getValue(), 
avg.getType()) + ", "
+                    + RuntimeProfile.MAX_TIME_PRE
+                    + RuntimeProfile.printCounter(max.getValue(), 
max.getType()) + ", "
+                    + RuntimeProfile.MIN_TIME_PRE
+                    + RuntimeProfile.printCounter(min.getValue(), 
min.getType());
+            return infoString;
+        } else {
+            String infoString = RuntimeProfile.printCounter(sum.getValue(), 
sum.getType());
+            return infoString;
+        }
+    }
+}
diff --git a/fe/fe-core/src/main/java/org/apache/doris/common/util/Counter.java 
b/fe/fe-core/src/main/java/org/apache/doris/common/util/Counter.java
index 2beb845438a..af9cd1e6cd6 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/common/util/Counter.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/common/util/Counter.java
@@ -23,7 +23,6 @@ import org.apache.doris.thrift.TUnit;
 public class Counter {
     private volatile long value;
     private volatile int type;
-    private volatile boolean remove = false;
     private volatile long level;
 
     public long getValue() {
@@ -70,6 +69,20 @@ public class Counter {
         this.value += other.value;
     }
 
+    public void minValue(Counter other) {
+        if (other == null) {
+            return;
+        }
+        this.value = Math.min(this.value, other.value);
+    }
+
+    public void maxValue(Counter other) {
+        if (other == null) {
+            return;
+        }
+        this.value = Math.max(this.value, other.value);
+    }
+
     public void divValue(long div) {
         if (div <= 0) {
             return;
@@ -82,15 +95,12 @@ public class Counter {
         return ttype == TUnit.TIME_MS || ttype == TUnit.TIME_NS || ttype == 
TUnit.TIME_S;
     }
 
-    public void setCanRemove() {
-        this.remove = true;
+    public long getLevel() {
+        return this.level;
     }
 
-    public boolean isRemove() {
-        return this.remove;
+    public String print() {
+        return RuntimeProfile.printCounter(value, getType());
     }
 
-    public long getLevel() {
-        return this.level;
-    }
 }
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/common/util/RuntimeProfile.java 
b/fe/fe-core/src/main/java/org/apache/doris/common/util/RuntimeProfile.java
index 3519ebce254..4e0602e8079 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/common/util/RuntimeProfile.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/common/util/RuntimeProfile.java
@@ -69,6 +69,7 @@ public class RuntimeProfile {
     private LinkedList<Pair<RuntimeProfile, Boolean>> childList = 
Lists.newLinkedList();
     private ReentrantReadWriteLock childLock = new ReentrantReadWriteLock();
 
+    private List<String> planNodeInfos = Lists.newArrayList();
     private String name;
 
     private Long timestamp = -1L;
@@ -83,7 +84,7 @@ public class RuntimeProfile {
     private Boolean isSinkOperator = false;
 
     private int profileLevel = 3;
-    private Planner planner = null;
+    private Map<Integer, String> planNodeMap = null;
     private int nodeid = -1;
 
     public RuntimeProfile(String name) {
@@ -92,6 +93,13 @@ public class RuntimeProfile {
         this.counterTotalTime = new Counter(TUnit.TIME_NS, 0, 1);
     }
 
+    public RuntimeProfile(String name, int nodeId) {
+        this();
+        this.name = name;
+        this.counterTotalTime = new Counter(TUnit.TIME_NS, 0, 3);
+        this.nodeid = nodeId;
+    }
+
     public RuntimeProfile() {
         this.counterTotalTime = new Counter(TUnit.TIME_NS, 0, 1);
         this.localTimePercent = 0;
@@ -134,6 +142,10 @@ public class RuntimeProfile {
         this.isPipelineX = isPipelineX;
     }
 
+    public boolean getIsPipelineX() {
+        return this.isPipelineX;
+    }
+
     public Map<String, Counter> getCounterMap() {
         return counterMap;
     }
@@ -179,6 +191,29 @@ public class RuntimeProfile {
         }
     }
 
+    public void addCounter(String name, Counter newCounter, String 
parentCounterName) {
+        counterLock.writeLock().lock();
+        try {
+            Counter counter = this.counterMap.get(name);
+            if (counter != null) {
+                return;
+            } else {
+                Preconditions.checkState(parentCounterName.equals(ROOT_COUNTER)
+                        || this.counterMap.containsKey(parentCounterName));
+                this.counterMap.put(name, newCounter);
+
+                Set<String> childCounters = 
childCounterMap.get(parentCounterName);
+                if (childCounters == null) {
+                    childCounterMap.put(parentCounterName, new 
TreeSet<String>());
+                    childCounters = childCounterMap.get(parentCounterName);
+                }
+                childCounters.add(name);
+            }
+        } finally {
+            counterLock.writeLock().unlock();
+        }
+    }
+
     public void update(final TRuntimeProfileTree thriftProfile) {
         Reference<Integer> idx = new Reference<Integer>(0);
         update(thriftProfile.nodes, idx);
@@ -339,6 +374,9 @@ public class RuntimeProfile {
         }
         builder.append("\n");
 
+        // plan node info
+        printPlanNodeInfo(prefix + "   ", builder);
+
         // 2. info String
         infoStringsLock.readLock().lock();
         try {
@@ -373,6 +411,17 @@ public class RuntimeProfile {
         }
     }
 
+    private void printPlanNodeInfo(String prefix, StringBuilder builder) {
+        if (planNodeInfos.isEmpty()) {
+            return;
+        }
+        builder.append(prefix + "- " + "PlanInfo\n");
+
+        for (String info : planNodeInfos) {
+            builder.append(prefix + "   - " + info + "\n");
+        }
+    }
+
     public void simpleProfile(int depth, int childIdx, ProfileStatistics 
statistics) {
         if (depth == FRAGMENT_DEPTH) {
             statistics.setFragmentId(childIdx);
@@ -528,15 +577,69 @@ public class RuntimeProfile {
         if (this.profileLevel == 3) {
             return toString();
         }
-        if (this.planner == null) {
+        if (this.planNodeMap == null) {
             return toString();
         }
-        StringBuilder builder = new StringBuilder();
-        prettyPrint(builder, "");
-        ProfileStatistics statistics = new ProfileStatistics(this.isPipelineX);
-        simpleProfile(0, 0, statistics);
-        String planerStr = this.planner.getExplainStringToProfile(statistics);
-        return "Simple profile \n \n " + planerStr + "\n \n \n" + 
builder.toString();
+        RuntimeProfile simpleProfile = new RuntimeProfile("SimpleProfile");
+        getSimpleProfile(0, simpleProfile, this.planNodeMap);
+        return simpleProfile.toString() + " \n \n " + toString();
+    }
+
+    public void getSimpleProfile(int depth, RuntimeProfile simpleProfile, 
Map<Integer, String> planNodeMap) {
+        if (depth == FRAGMENT_DEPTH) {
+            gettSimpleProfileFromMutiInstance(childList, simpleProfile, 
planNodeMap);
+            return;
+        }
+        for (int i = 0; i < childList.size(); i++) {
+            Pair<RuntimeProfile, Boolean> pair = childList.get(i);
+            RuntimeProfile profile = pair.first;
+            profile.getSimpleProfile(depth + 1, simpleProfile, planNodeMap);
+        }
+    }
+
+    public static void 
gettSimpleProfileFromMutiInstance(LinkedList<Pair<RuntimeProfile, Boolean>> 
childList,
+            RuntimeProfile simpleProfile, Map<Integer, String> planNodeMap) {
+        RuntimeProfile oneProfile = childList.get(0).first;
+        int instanceNum = childList.size();
+        RuntimeProfile mergedProfile = new RuntimeProfile("Instance" + "(" + 
instanceNum + ")", oneProfile.nodeid);
+        LinkedList<RuntimeProfile> other = new LinkedList<RuntimeProfile>();
+        for (int i = 1; i < childList.size(); i++) {
+            other.add(childList.get(i).first);
+        }
+        simpleProfile.addChildWithCheck(mergedProfile, planNodeMap);
+        collecteProfile(oneProfile, other, mergedProfile, planNodeMap);
+    }
+
+    public static void collecteProfile(RuntimeProfile src, 
LinkedList<RuntimeProfile> others,
+            RuntimeProfile simpleProfile, Map<Integer, String> planNodeMap) {
+        collecteProfileCounter(src, ROOT_COUNTER, others, simpleProfile);
+        for (int i = 0; i < src.childList.size(); i++) {
+            RuntimeProfile srcChild = src.childList.get(i).first;
+            LinkedList<RuntimeProfile> rhsChild = getChildListFromLists(i, 
others);
+            RuntimeProfile childProfile = new RuntimeProfile(srcChild.name, 
srcChild.nodeId());
+            simpleProfile.addChildWithCheck(childProfile, planNodeMap);
+            collecteProfile(srcChild, rhsChild, childProfile, planNodeMap);
+        }
+    }
+
+    private static void collecteProfileCounter(RuntimeProfile src, String 
counterName, LinkedList<RuntimeProfile> rhs,
+            RuntimeProfile simpleProfile) {
+        Set<String> childCounterSet = src.childCounterMap.get(counterName);
+        if (childCounterSet == null) {
+            return;
+        }
+        List<String> childCounterList = new LinkedList<>(childCounterSet);
+        for (String childCounterName : childCounterList) {
+            Counter counter = src.counterMap.get(childCounterName);
+            collecteProfileCounter(src, childCounterName, rhs, simpleProfile);
+            if (counter.getLevel() == 1) {
+                LinkedList<Counter> rhsCounter = 
getCounterListFromLists(childCounterName, rhs);
+                // String info = getMergeString(counter, rhsCounter);
+                AggCounter aggCounter = new AggCounter(counter.getType(), 
counter.getValue());
+                aggCounter.addCounters(rhsCounter);
+                simpleProfile.addCounter(childCounterName, aggCounter, 
ROOT_COUNTER);
+            }
+        }
     }
 
     private void printChildCounters(String prefix, String counterName, 
StringBuilder builder) {
@@ -551,7 +654,7 @@ public class RuntimeProfile {
                 Counter counter = this.counterMap.get(childCounterName);
                 Preconditions.checkState(counter != null);
                 builder.append(prefix).append("   - 
").append(childCounterName).append(": ")
-                        .append(printCounter(counter.getValue(), 
counter.getType())).append("\n");
+                        .append(counter.print()).append("\n");
                 this.printChildCounters(prefix + "  ", childCounterName, 
builder);
             }
         } finally {
@@ -657,6 +760,33 @@ public class RuntimeProfile {
         }
     }
 
+    public void addChildWithCheck(RuntimeProfile child, Map<Integer, String> 
planNodeMap) {
+        // check name
+        if (child.name.startsWith("PipelineTask") || 
child.name.startsWith("PipelineContext")) {
+            return;
+        }
+        childLock.writeLock().lock();
+        try {
+            Pair<RuntimeProfile, Boolean> pair = Pair.of(child, true);
+            this.childList.add(pair);
+        } finally {
+            childLock.writeLock().unlock();
+        }
+        // insert plan node info to profile strinfo
+        if (!planNodeMap.containsKey(child.nodeId())) {
+            return;
+        }
+        child.addPlanNodeInfos(planNodeMap.get(child.nodeId()));
+        planNodeMap.remove(child.nodeId());
+    }
+
+    public void addPlanNodeInfos(String infos) {
+        String[] infoList = infos.split("\n");
+        for (String info : infoList) {
+            planNodeInfos.add(info);
+        }
+    }
+
     public void addFirstChild(RuntimeProfile child) {
         if (child == null) {
             return;
@@ -689,8 +819,10 @@ public class RuntimeProfile {
         this.profileLevel = profileLevel;
     }
 
-    public void setPlaner(Planner planner) {
-        this.planner = planner;
+    public void setFragmentPlanInfo(Planner planner) {
+        if (planner != null) {
+            this.planNodeMap = planner.getExplainStringMap();
+        }
     }
 
     private void computeTimeInProfile(long total) {
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/planner/PlanFragment.java 
b/fe/fe-core/src/main/java/org/apache/doris/planner/PlanFragment.java
index 26c09e439e6..3324f9de1b1 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/planner/PlanFragment.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/planner/PlanFragment.java
@@ -43,6 +43,7 @@ import org.apache.logging.log4j.Logger;
 import java.util.ArrayList;
 import java.util.HashSet;
 import java.util.List;
+import java.util.Map;
 import java.util.Set;
 import java.util.stream.Collectors;
 
@@ -355,6 +356,13 @@ public class PlanFragment extends TreeNode<PlanFragment> {
         return str.toString();
     }
 
+    public void getExplainStringMap(Map<Integer, String> planNodeMap) {
+        org.apache.doris.thrift.TExplainLevel explainLevel = 
org.apache.doris.thrift.TExplainLevel.NORMAL;
+        if (planRoot != null) {
+            planRoot.getExplainStringMap(explainLevel, planNodeMap);
+        }
+    }
+
     /**
      * Returns true if this fragment is partitioned.
      */
diff --git a/fe/fe-core/src/main/java/org/apache/doris/planner/PlanNode.java 
b/fe/fe-core/src/main/java/org/apache/doris/planner/PlanNode.java
index 754b9fcfcb2..c323b3160fb 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/planner/PlanNode.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/planner/PlanNode.java
@@ -63,6 +63,7 @@ import java.util.Collection;
 import java.util.Collections;
 import java.util.HashSet;
 import java.util.List;
+import java.util.Map;
 import java.util.Set;
 
 /**
@@ -631,6 +632,27 @@ public abstract class PlanNode extends TreeNode<PlanNode> 
implements PlanStats {
         return expBuilder.toString();
     }
 
+    private String getplanNodeExplainString(String prefix, TExplainLevel 
detailLevel) {
+        StringBuilder expBuilder = new StringBuilder();
+        expBuilder.append(getNodeExplainString(prefix, detailLevel));
+        if (limit != -1) {
+            expBuilder.append(prefix + "limit: " + limit + "\n");
+        }
+        if (!CollectionUtils.isEmpty(projectList)) {
+            expBuilder.append(prefix).append("projections: 
").append(getExplainString(projectList)).append("\n");
+            expBuilder.append(prefix).append("project output tuple id: ")
+                    .append(outputTupleDesc.getId().asInt()).append("\n");
+        }
+        return expBuilder.toString();
+    }
+
+    public void getExplainStringMap(TExplainLevel detailLevel, Map<Integer, 
String> planNodeMap) {
+        planNodeMap.put(id.asInt(), getplanNodeExplainString("", detailLevel));
+        for (int i = 0; i < children.size(); ++i) {
+            children.get(i).getExplainStringMap(detailLevel, planNodeMap);
+        }
+    }
+
     /**
      * Return the node-specific details.
      * Subclass should override this function.
diff --git a/fe/fe-core/src/main/java/org/apache/doris/planner/Planner.java 
b/fe/fe-core/src/main/java/org/apache/doris/planner/Planner.java
index 8681455a399..e03c696dfd9 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/planner/Planner.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/planner/Planner.java
@@ -39,7 +39,9 @@ import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
 
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 import java.util.Optional;
 
 public abstract class Planner {
@@ -105,6 +107,15 @@ public abstract class Planner {
         return str.toString();
     }
 
+    public Map<Integer, String> getExplainStringMap() {
+        Map<Integer, String> planNodeMap = new HashMap<Integer, String>();
+        for (int i = 0; i < fragments.size(); ++i) {
+            PlanFragment fragment = fragments.get(i);
+            fragment.getExplainStringMap(planNodeMap);
+        }
+        return planNodeMap;
+    }
+
     protected void handleLiteralInFe(LiteralExpr literalExpr, List<String> 
data) {
         if (literalExpr instanceof NullLiteral) {
             data.add(null);


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to