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 c18a471303 [Optimize](predicate)  update inplace on VcompoundPred  
(#14402)
c18a471303 is described below

commit c18a4713036994b7c5b436ab037d5b691bdc2607
Author: Pxl <[email protected]>
AuthorDate: Mon Nov 21 09:12:30 2022 +0800

    [Optimize](predicate)  update inplace on VcompoundPred  (#14402)
    
    select count(*) from lineorder where lo_orderkey<100000000 OR 
lo_orderkey>100000000 AND lo_orderkey<200000000 OR lo_orderkey >200000000;
    
    0.6s -> 0.5s
---
 .clang-tidy                             |   8 +-
 be/src/vec/exprs/vcompound_pred.h       | 166 ++++++++++++++++++++++++++++----
 be/src/vec/exprs/vectorized_fn_call.cpp |   2 +-
 be/src/vec/exprs/vectorized_fn_call.h   |  24 ++---
 be/src/vec/exprs/vexpr.h                |   2 +
 5 files changed, 166 insertions(+), 36 deletions(-)

diff --git a/.clang-tidy b/.clang-tidy
index 7b4a2a53a0..62295d27b9 100644
--- a/.clang-tidy
+++ b/.clang-tidy
@@ -3,19 +3,19 @@ Checks: |
   clang-diagnostic-*,
   clang-analyzer-*,
   -*,
+  bugprone-redundant-branch-condition,
   modernize-use-override,
   modernize-use-equals-default,
   modernize-use-equals-delete,
   modernize-use-nullptr,
   modernize-use-bool-literals,
   modernize-use-using,
+  misc-redundant-expression,
+  misc-unused-*,
   readability-make-member-function-const,
   readability-non-const-parameter,
   readability-static-accessed-through-instance,
-  readability-redundant-smartptr-get,
-  readability-redundant-member-init,
-  readability-redundant-string-cstr,
-  readability-redundant-string-init,
+  readability-redundant-*,
   readability-braces-around-statements,
   portability-simd-intrinsics,
   performance-type-promotion-in-math-fn,
diff --git a/be/src/vec/exprs/vcompound_pred.h 
b/be/src/vec/exprs/vcompound_pred.h
index 5d3e6be25c..156c10ce54 100644
--- a/be/src/vec/exprs/vcompound_pred.h
+++ b/be/src/vec/exprs/vcompound_pred.h
@@ -16,38 +16,170 @@
 // under the License.
 
 #pragma once
-#include "runtime/runtime_state.h"
+#include <gen_cpp/Opcodes_types.h>
+
+#include "common/status.h"
+#include "util/simd/bits.h"
+#include "vec/columns/column.h"
+#include "vec/columns/columns_number.h"
+#include "vec/common/assert_cast.h"
 #include "vec/exprs/vectorized_fn_call.h"
 #include "vec/exprs/vexpr.h"
-#include "vec/functions/function.h"
 
 namespace doris::vectorized {
 
-class VcompoundPred final : public VectorizedFnCall {
+inline std::string compound_operator_to_string(TExprOpcode::type op) {
+    if (op == TExprOpcode::COMPOUND_AND) {
+        return "and";
+    } else if (op == TExprOpcode::COMPOUND_OR) {
+        return "or";
+    } else {
+        return "not";
+    }
+}
+
+class VcompoundPred : public VectorizedFnCall {
 public:
     VcompoundPred(const TExprNode& node) : VectorizedFnCall(node) {
-        switch (node.opcode) {
-        case TExprOpcode::COMPOUND_AND:
-            _fn.name.function_name = "and";
-            break;
-        case TExprOpcode::COMPOUND_OR:
-            _fn.name.function_name = "or";
-            break;
-        default:
-            _fn.name.function_name = "not";
-            break;
+        _op = node.opcode;
+        _fn.name.function_name = compound_operator_to_string(_op);
+        _expr_name = "CompoundPredicate (" + _fn.name.function_name + ")";
+    }
+
+    VExpr* clone(ObjectPool* pool) const override { return pool->add(new 
VcompoundPred(*this)); }
+
+    const std::string& expr_name() const override { return _expr_name; }
+
+    Status execute(VExprContext* context, doris::vectorized::Block* block,
+                   int* result_column_id) override {
+        if (children().size() == 1 || !_all_child_is_compound_and_not_const()) 
{
+            return VectorizedFnCall::execute(context, block, result_column_id);
+        }
+
+        int lhs_id = -1;
+        int rhs_id = -1;
+        RETURN_IF_ERROR(_children[0]->execute(context, block, &lhs_id));
+        ColumnPtr lhs_column = block->get_by_position(lhs_id).column;
+
+        ColumnPtr rhs_column = nullptr;
+
+        size_t size = lhs_column->size();
+        uint8* __restrict data = _get_raw_data(lhs_column);
+        int filted = simd::count_zero_num((int8_t*)data, size);
+        bool full = filted == 0;
+        bool empty = filted == size;
+
+        const uint8* __restrict data_rhs = nullptr;
+        bool full_rhs = false;
+        bool empty_rhs = false;
+
+        auto get_rhs_colum = [&]() {
+            if (rhs_id == -1) {
+                RETURN_IF_ERROR(_children[1]->execute(context, block, 
&rhs_id));
+                rhs_column = block->get_by_position(rhs_id).column;
+                data_rhs = _get_raw_data(rhs_column);
+                if (!empty) {
+                    if (const uint8* null_map =
+                                
_get_null_map(block->get_by_position(rhs_id).column);
+                        null_map != nullptr) {
+                        for (size_t i = 0; i < size; i++) {
+                            data[i] &= !null_map[i];
+                        }
+                    }
+                }
+                int filted = simd::count_zero_num((int8_t*)data_rhs, size);
+                full_rhs = filted == 0;
+                empty_rhs = filted == size;
+            }
+            return Status::OK();
+        };
+
+        if (_op == TExprOpcode::COMPOUND_AND) {
+            if (!empty) { // empty and any = empty, so lhs should not empty
+                RETURN_IF_ERROR(get_rhs_colum());
+                if (empty_rhs) { // any and empty = empty
+                    *result_column_id = rhs_id;
+                    return Status::OK();
+                } else if (!full_rhs) { // any and full = any, so rhs should 
not full.
+                    for (size_t i = 0; i < size; i++) {
+                        data[i] &= data_rhs[i];
+                    }
+                }
+            }
+        } else if (_op == TExprOpcode::COMPOUND_OR) {
+            if (!full) { // full or any = full, so lhs should not full
+                RETURN_IF_ERROR(get_rhs_colum());
+                if (full_rhs) { // any or full = full
+                    *result_column_id = rhs_id;
+                    return Status::OK();
+                } else if (!empty_rhs) { // any or empty = any, so rhs should 
not empty
+                    for (size_t i = 0; i < size; i++) {
+                        data[i] |= data_rhs[i];
+                    }
+                }
+            }
+        } else {
+            LOG(FATAL) << "Compound operator must be AND or OR.";
         }
+
+        *result_column_id = lhs_id;
+        return Status::OK();
     }
 
     std::string debug_string() const override {
         std::stringstream out;
-        out << "CompoundPredicate {" << _fn.name.function_name;
-        out << " (" << _children[0]->debug_string();
+        out << _expr_name << "{\n";
+        out << _children[0]->debug_string();
         if (children().size() > 1) {
-            out << ", " << _children[1]->debug_string();
+            out << ",\n" << _children[1]->debug_string();
         }
-        out << ")}";
+        out << "}";
         return out.str();
     }
+
+    bool is_compound_predicate() const override { return true; }
+
+private:
+    bool _all_child_is_compound_and_not_const() const {
+        for (auto child : _children) {
+            // we can make sure non const compound predicate's return column 
is allow modifyied locally.
+            if (child->is_constant() || !child->is_compound_predicate()) {
+                return false;
+            }
+        }
+        return false;
+    }
+
+    uint8* _get_raw_data(ColumnPtr column) const {
+        if (column->is_nullable()) {
+            return reinterpret_cast<ColumnUInt8*>(
+                           
assert_cast<ColumnNullable*>(column->assume_mutable().get())
+                                   ->get_nested_column_ptr()
+                                   .get())
+                    ->get_data()
+                    .data();
+        } else {
+            return 
reinterpret_cast<ColumnUInt8*>(column->assume_mutable().get())
+                    ->get_data()
+                    .data();
+        }
+    }
+
+    uint8* _get_null_map(ColumnPtr column) const {
+        if (column->is_nullable()) {
+            return reinterpret_cast<ColumnUInt8*>(
+                           
reinterpret_cast<ColumnNullable*>(column->assume_mutable().get())
+                                   ->get_null_map_column_ptr()
+                                   .get())
+                    ->get_data()
+                    .data();
+        } else {
+            return nullptr;
+        }
+    }
+
+    TExprOpcode::type _op;
+
+    std::string _expr_name;
 };
 } // namespace doris::vectorized
diff --git a/be/src/vec/exprs/vectorized_fn_call.cpp 
b/be/src/vec/exprs/vectorized_fn_call.cpp
index c535ca266f..3999599716 100644
--- a/be/src/vec/exprs/vectorized_fn_call.cpp
+++ b/be/src/vec/exprs/vectorized_fn_call.cpp
@@ -126,7 +126,7 @@ std::string VectorizedFnCall::debug_string() const {
         } else {
             out << ",";
         }
-        out << input_expr->debug_string();
+        out << "\n" << input_expr->debug_string();
     }
     out << "}";
     return out.str();
diff --git a/be/src/vec/exprs/vectorized_fn_call.h 
b/be/src/vec/exprs/vectorized_fn_call.h
index cdd3ef211e..63a11847db 100644
--- a/be/src/vec/exprs/vectorized_fn_call.h
+++ b/be/src/vec/exprs/vectorized_fn_call.h
@@ -23,20 +23,16 @@
 namespace doris::vectorized {
 class VectorizedFnCall : public VExpr {
 public:
-    VectorizedFnCall(const doris::TExprNode& node);
-    virtual doris::Status execute(VExprContext* context, 
doris::vectorized::Block* block,
-                                  int* result_column_id) override;
-    virtual doris::Status prepare(doris::RuntimeState* state, const 
doris::RowDescriptor& desc,
-                                  VExprContext* context) override;
-    virtual doris::Status open(doris::RuntimeState* state, VExprContext* 
context,
-                               FunctionContext::FunctionStateScope scope) 
override;
-    virtual void close(doris::RuntimeState* state, VExprContext* context,
-                       FunctionContext::FunctionStateScope scope) override;
-    virtual VExpr* clone(doris::ObjectPool* pool) const override {
-        return pool->add(new VectorizedFnCall(*this));
-    }
-    virtual const std::string& expr_name() const override;
-    virtual std::string debug_string() const override;
+    VectorizedFnCall(const TExprNode& node);
+    Status execute(VExprContext* context, Block* block, int* result_column_id) 
override;
+    Status prepare(RuntimeState* state, const RowDescriptor& desc, 
VExprContext* context) override;
+    Status open(RuntimeState* state, VExprContext* context,
+                FunctionContext::FunctionStateScope scope) override;
+    void close(RuntimeState* state, VExprContext* context,
+               FunctionContext::FunctionStateScope scope) override;
+    VExpr* clone(ObjectPool* pool) const override { return pool->add(new 
VectorizedFnCall(*this)); }
+    const std::string& expr_name() const override;
+    std::string debug_string() const override;
     static std::string debug_string(const std::vector<VectorizedFnCall*>& 
exprs);
 
 private:
diff --git a/be/src/vec/exprs/vexpr.h b/be/src/vec/exprs/vexpr.h
index 35b78635ab..beefec98e0 100644
--- a/be/src/vec/exprs/vexpr.h
+++ b/be/src/vec/exprs/vexpr.h
@@ -134,6 +134,8 @@ public:
 
     bool is_and_expr() const { return _fn.name.function_name == "and"; }
 
+    virtual bool is_compound_predicate() const { return false; }
+
     const TFunction& fn() const { return _fn; }
 
     /// Returns true if expr doesn't contain slotrefs, i.e., can be evaluated


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

Reply via email to