[Optimization](functions)Optimize function call for const columns. (#18310)

This commit is contained in:
zclllyybb
2023-04-12 11:11:01 +08:00
committed by GitHub
parent 49a9956986
commit 43392918cd
25 changed files with 1718 additions and 849 deletions

View File

@ -16,6 +16,9 @@
// under the License.
#include "exprs/math_functions.h"
#include "vec/columns/column_const.h"
#include "vec/columns/column_nullable.h"
#include "vec/core/types.h"
#include "vec/data_types/data_type_number.h"
#include "vec/data_types/data_type_string.h"
#include "vec/functions/simple_function_factory.h"
@ -49,29 +52,42 @@ public:
auto result_column = ColumnString::create();
auto result_null_map_column = ColumnUInt8::create(input_rows_count, 0);
bool col_const[3];
ColumnPtr argument_columns[3];
for (int i = 0; i < 3; ++i) {
argument_columns[i] =
block.get_by_position(arguments[i]).column->convert_to_full_column_if_const();
if (auto* nullable = check_and_get_column<ColumnNullable>(*argument_columns[i])) {
// Danger: Here must dispose the null map data first! Because
// argument_columns[i]=nullable->get_nested_column_ptr(); will release the mem
// of column nullable mem of null map
VectorizedUtils::update_null_map(result_null_map_column->get_data(),
nullable->get_null_map_data());
argument_columns[i] = nullable->get_nested_column_ptr();
}
col_const[i] = is_column_const(*block.get_by_position(arguments[i]).column);
}
argument_columns[0] = col_const[0] ? static_cast<const ColumnConst&>(
*block.get_by_position(arguments[0]).column)
.convert_to_full_column()
: block.get_by_position(arguments[0]).column;
default_preprocess_parameter_columns(argument_columns, col_const, {1, 2}, block, arguments);
for (int i = 0; i < 3; i++) {
check_set_nullable(argument_columns[i], result_null_map_column);
}
execute_straight(
context,
assert_cast<const typename Impl::DataType::ColumnType*>(argument_columns[0].get()),
assert_cast<const ColumnInt8*>(argument_columns[1].get()),
assert_cast<const ColumnInt8*>(argument_columns[2].get()),
assert_cast<ColumnString*>(result_column.get()),
assert_cast<ColumnUInt8*>(result_null_map_column.get())->get_data(),
input_rows_count);
if (col_const[1] && col_const[2]) {
execute_scalar_args(
context,
assert_cast<const typename Impl::DataType::ColumnType*>(
argument_columns[0].get()),
assert_cast<const ColumnInt8*>(argument_columns[1].get())->get_element(0),
assert_cast<const ColumnInt8*>(argument_columns[2].get())->get_element(0),
assert_cast<ColumnString*>(result_column.get()),
assert_cast<ColumnUInt8*>(result_null_map_column.get())->get_data(),
input_rows_count);
} else {
execute_straight(context,
assert_cast<const typename Impl::DataType::ColumnType*>(
argument_columns[0].get()),
assert_cast<const ColumnInt8*>(argument_columns[1].get()),
assert_cast<const ColumnInt8*>(argument_columns[2].get()),
assert_cast<ColumnString*>(result_column.get()),
assert_cast<ColumnUInt8*>(result_null_map_column.get())->get_data(),
input_rows_count);
}
block.get_by_position(result).column =
ColumnNullable::create(std::move(result_column), std::move(result_null_map_column));
@ -79,28 +95,49 @@ public:
}
private:
void execute_straight(FunctionContext* context,
const typename Impl::DataType::ColumnType* data_column,
const ColumnInt8* src_base_column, const ColumnInt8* dst_base_column,
ColumnString* result_column, NullMap& result_null_map,
size_t input_rows_count) {
// check out of bound.
static bool _check_oob(const Int8 src_base, const Int8 dst_base) {
return std::abs(src_base) < MathFunctions::MIN_BASE ||
std::abs(src_base) > MathFunctions::MAX_BASE ||
std::abs(dst_base) < MathFunctions::MIN_BASE ||
std::abs(dst_base) > MathFunctions::MAX_BASE;
}
static void execute_straight(FunctionContext* context,
const typename Impl::DataType::ColumnType* data_column,
const ColumnInt8* src_base_column,
const ColumnInt8* dst_base_column, ColumnString* result_column,
NullMap& result_null_map, size_t input_rows_count) {
for (size_t i = 0; i < input_rows_count; i++) {
if (result_null_map[i]) {
result_column->insert_default();
continue;
}
Int8 src_base = src_base_column->get_element(i);
Int8 dst_base = dst_base_column->get_element(i);
if (std::abs(src_base) < MathFunctions::MIN_BASE ||
std::abs(src_base) > MathFunctions::MAX_BASE ||
std::abs(dst_base) < MathFunctions::MIN_BASE ||
std::abs(dst_base) > MathFunctions::MAX_BASE) {
if (_check_oob(src_base, dst_base)) {
result_null_map[i] = true;
result_column->insert_default();
} else {
Impl::calculate_cell(context, data_column, src_base, dst_base, result_column,
result_null_map, i);
}
}
}
static void execute_scalar_args(FunctionContext* context,
const typename Impl::DataType::ColumnType* data_column,
const Int8 src_base, const Int8 dst_base,
ColumnString* result_column, NullMap& result_null_map,
size_t input_rows_count) {
if (_check_oob(src_base, dst_base)) {
result_null_map.assign(input_rows_count, UInt8 {true});
result_column->insert_many_defaults(input_rows_count);
return;
}
for (size_t i = 0; i < input_rows_count; i++) {
if (result_null_map[i]) {
result_column->insert_default();
continue;
}
Impl::calculate_cell(context, data_column, src_base, dst_base, result_column,
result_null_map, i);
}