Skip to content

Commit 932caea

Browse files
committed
improve performance
1 parent 838b8cb commit 932caea

File tree

2 files changed

+56
-51
lines changed

2 files changed

+56
-51
lines changed

src/Columns/MaskOperations.cpp

Lines changed: 40 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -91,32 +91,50 @@ static size_t extractMaskNumericImpl(
9191
size_t ones_count = 0;
9292
size_t mask_size = mask.size();
9393

94-
for (size_t i = 0; i != mask_size; ++i)
94+
if (!null_bytemap)
9595
{
96-
// Change mask only where value is 1.
97-
if (!mask[i])
98-
continue;
99-
100-
UInt8 value;
101-
if (null_bytemap && (*null_bytemap)[i])
96+
/// Fast path when null_bytemap is not provided.
97+
for (size_t i = 0; i != mask_size; ++i)
10298
{
103-
value = null_value;
104-
if (nulls)
105-
(*nulls)[i] = 1;
99+
UInt8 value;
100+
if constexpr (!inverted)
101+
value = static_cast<bool>(data[i]);
102+
else
103+
value = !static_cast<bool>(data[i]);
104+
105+
ones_count += value;
106+
mask[i] &= value;
106107
}
107-
else
108-
value = static_cast<bool>(data[i]);
109-
110-
if constexpr (inverted)
111-
value = !value;
112-
113-
if (value)
114-
++ones_count;
115-
116-
mask[i] = value;
108+
return ones_count;
109+
}
110+
else
111+
{
112+
for (size_t i = 0; i != mask_size; ++i)
113+
{
114+
// Change mask only where value is 1.
115+
if (!mask[i])
116+
continue;
117+
118+
UInt8 value;
119+
if (null_bytemap && (*null_bytemap)[i])
120+
{
121+
value = null_value;
122+
if (nulls)
123+
(*nulls)[i] = 1;
124+
}
125+
else
126+
value = static_cast<bool>(data[i]);
127+
128+
if constexpr (inverted)
129+
value = !value;
130+
131+
if (value)
132+
++ones_count;
133+
134+
mask[i] = value;
135+
}
136+
return ones_count;
117137
}
118-
119-
return ones_count;
120138
}
121139

122140
template <bool inverted, typename NumericType>

src/Functions/IFunction.cpp

Lines changed: 16 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -216,8 +216,8 @@ ColumnPtr IExecutableFunction::defaultImplementationForNulls(
216216
if (input_rows_count == 0)
217217
return result_type->createColumn();
218218

219-
IColumn::Filter mask(input_rows_count, 1);
220-
MaskInfo mask_info = {.has_ones = true, .has_zeros = false};
219+
auto result_null_map = ColumnUInt8::create(input_rows_count, 0);
220+
auto & result_null_map_data = result_null_map->getData();
221221
bool all_columns_constant = true;
222222
for (const auto & arg : args)
223223
{
@@ -236,29 +236,27 @@ ColumnPtr IExecutableFunction::defaultImplementationForNulls(
236236
}
237237
else
238238
{
239-
const auto & null_map = assert_cast<const ColumnNullable &>(*arg.column).getNullMapColumnPtr();
240-
mask_info = extractInvertedMask(mask, null_map);
239+
const auto & null_map = assert_cast<const ColumnNullable &>(*arg.column).getNullMapData();
240+
for (size_t i = 0; i < input_rows_count; ++i)
241+
result_null_map_data[i] |= null_map[i];
241242
}
242243
}
243-
244-
/// Exit loop early if each row contains at least one null value
245-
if (!mask_info.has_ones)
246-
break;
247244
}
248245

249-
if (!mask_info.has_ones && !all_columns_constant)
246+
size_t rows_with_nulls = countBytesInFilter(result_null_map_data.data(), 0, input_rows_count);
247+
size_t rows_without_nulls = input_rows_count - rows_with_nulls;
248+
ProfileEvents::increment(ProfileEvents::DefaultImplementationForNullsRows, input_rows_count);
249+
ProfileEvents::increment(ProfileEvents::DefaultImplementationForNullsRowsWithNulls, rows_with_nulls);
250+
251+
if (rows_without_nulls == 0 && !all_columns_constant)
250252
{
251253
/// Don't need to evaluate function if each row contains at least one null value and not all input columns are constant.
252254
return result_type->createColumnConstWithDefaultValue(input_rows_count)->convertToFullColumnIfConst();
253255
}
254256

255-
size_t rows_without_nulls = countBytesInFilter(mask.data(), 0, mask.size());
256-
size_t rows_with_nulls = mask.size() - rows_without_nulls;
257-
double null_ratio = rows_with_nulls / static_cast<double>(mask.size());
257+
double null_ratio = rows_with_nulls / static_cast<double>(result_null_map_data.size());
258258
bool should_short_circuit = short_circuit_function_evaluation_for_nulls && !all_columns_constant
259259
&& null_ratio >= short_circuit_function_evaluation_for_nulls_threshold;
260-
ProfileEvents::increment(ProfileEvents::DefaultImplementationForNullsRows, mask.size());
261-
ProfileEvents::increment(ProfileEvents::DefaultImplementationForNullsRowsWithNulls, rows_with_nulls);
262260

263261
ColumnsWithTypeAndName temporary_columns = createBlockWithNestedColumns(args);
264262
auto temporary_result_type = removeNullable(result_type);
@@ -267,13 +265,7 @@ ColumnPtr IExecutableFunction::defaultImplementationForNulls(
267265
{
268266
/// Each row should be evaluated if there are no nulls or short circuiting is disabled.
269267
auto res = executeWithoutLowCardinalityColumns(temporary_columns, temporary_result_type, input_rows_count, dry_run);
270-
271-
/// Invert mask as null map
272-
inverseMask(mask, mask_info);
273-
auto null_map = ColumnUInt8::create();
274-
null_map->getData() = std::move(mask);
275-
276-
auto new_res = wrapInNullable(res, std::move(null_map));
268+
auto new_res = wrapInNullable(res, std::move(result_null_map));
277269
return new_res;
278270
}
279271
else
@@ -282,18 +274,13 @@ ColumnPtr IExecutableFunction::defaultImplementationForNulls(
282274

283275
/// Filter every column by mask
284276
for (auto & col : temporary_columns)
285-
col.column = col.column->filter(mask, rows_without_nulls);
277+
col.column = col.column->filter(result_null_map_data, rows_without_nulls);
286278

287279
auto res = executeWithoutLowCardinalityColumns(temporary_columns, temporary_result_type, rows_without_nulls, dry_run);
288280
auto mutable_res = IColumn::mutate(std::move(res));
289-
mutable_res->expand(mask, false);
290-
291-
/// Invert mask as null map
292-
inverseMask(mask, mask_info);
293-
auto null_map = ColumnUInt8::create();
294-
null_map->getData() = std::move(mask);
281+
mutable_res->expand(result_null_map_data, false);
295282

296-
auto new_res = wrapInNullable(std::move(mutable_res), std::move(null_map));
283+
auto new_res = wrapInNullable(std::move(mutable_res), std::move(result_null_map));
297284
return new_res;
298285
}
299286
}

0 commit comments

Comments
 (0)