Skip to content

Commit 5025383

Browse files
mbasmanovafacebook-github-bot
authored andcommitted
Add benchmark for Presto IN expression (facebookincubator#516)
Summary: The benchmark shows that IN expression with large number of values is incredibly slow. This is because IN is implemented as a function with variable number of arguments. IN with 10K values is represented as an expression tree with one node for the IN, one for the column and 10K nodes for values. Each value is wrapped in a ConstantExpr which gets evaluated for each batch of rows making ne shared pointers to constant vectors. A follow-up PR will optimize IN expression to take values as a single array. ``` prestosql/benchmarks/InBenchmark.cpprelative time/iter iters/s ============================================================================ fastIn 3.49ms 286.17 in 55.08% 6.34ms 157.62 fastIn10K 3.12ms 320.43 in10K 0.07% 4.72s 211.75m ============================================================================ ``` Pull Request resolved: facebookincubator#516 Differential Revision: D31997776 Pulled By: mbasmanova fbshipit-source-id: 359d76141b472922f31b78edcfab19282e8b67e7
1 parent 1993f75 commit 5025383

File tree

3 files changed

+166
-25
lines changed

3 files changed

+166
-25
lines changed

velox/functions/prestosql/benchmarks/ArrayMinMaxBenchmark.cpp

+9-11
Original file line numberDiff line numberDiff line change
@@ -98,15 +98,19 @@ class ArrayMinMaxBenchmark : public functions::test::FunctionBenchmarkBase {
9898
{"array_max_simple"});
9999
}
100100

101-
void runInteger(const std::string& functionName) {
102-
folly::BenchmarkSuspender suspender;
103-
vector_size_t size = 1'000;
101+
RowVectorPtr makeData() {
102+
const vector_size_t size = 1'000;
104103
auto arrayVector = vectorMaker_.arrayVector<int32_t>(
105104
size,
106105
[](auto row) { return row % 5; },
107106
[](auto row) { return row % 23; });
108107

109-
auto rowVector = vectorMaker_.rowVector({arrayVector});
108+
return vectorMaker_.rowVector({arrayVector});
109+
}
110+
111+
void runInteger(const std::string& functionName) {
112+
folly::BenchmarkSuspender suspender;
113+
auto rowVector = makeData();
110114
auto exprSet = compileExpression(
111115
fmt::format("{}(c0)", functionName), rowVector->type());
112116
suspender.dismiss();
@@ -125,13 +129,7 @@ class ArrayMinMaxBenchmark : public functions::test::FunctionBenchmarkBase {
125129
template <typename F>
126130
void runFastInteger(F function) {
127131
folly::BenchmarkSuspender suspender;
128-
vector_size_t size = 1'000;
129-
auto arrayVector = vectorMaker_.arrayVector<int32_t>(
130-
size,
131-
[](auto row) { return row % 5; },
132-
[](auto row) { return row % 23; });
133-
134-
auto rowVector = vectorMaker_.rowVector({arrayVector});
132+
auto arrayVector = makeData()->childAt(0);
135133
suspender.dismiss();
136134

137135
int cnt = 0;

velox/functions/prestosql/benchmarks/CMakeLists.txt

+23-14
Original file line numberDiff line numberDiff line change
@@ -23,32 +23,41 @@ set(BENCHMARK_DEPENDENCIES
2323
${FOLLY_WITH_DEPENDENCIES}
2424
${FOLLY_BENCHMARK})
2525

26-
add_executable(velox_functions_benchmarks_array_contains
26+
add_executable(velox_functions_prestosql_benchmarks_array_contains
2727
ArrayContainsBenchmark.cpp)
28-
target_link_libraries(velox_functions_benchmarks_array_contains
28+
target_link_libraries(velox_functions_prestosql_benchmarks_array_contains
2929
${BENCHMARK_DEPENDENCIES})
3030

31-
add_executable(velox_functions_benchmarks_array_min_max
31+
add_executable(velox_functions_prestosql_benchmarks_array_min_max
3232
ArrayMinMaxBenchmark.cpp)
33-
target_link_libraries(velox_functions_benchmarks_array_min_max
33+
target_link_libraries(velox_functions_prestosql_benchmarks_array_min_max
3434
${BENCHMARK_DEPENDENCIES})
3535

36-
add_executable(velox_functions_benchmarks_width_bucket WidthBucketBenchmark.cpp)
37-
target_link_libraries(velox_functions_benchmarks_width_bucket
36+
add_executable(velox_functions_prestosql_benchmarks_width_bucket
37+
WidthBucketBenchmark.cpp)
38+
target_link_libraries(velox_functions_prestosql_benchmarks_width_bucket
3839
${BENCHMARK_DEPENDENCIES})
3940

40-
add_executable(velox_functions_benchmarks_string_ascii_utf_functions
41+
add_executable(velox_functions_prestosql_benchmarks_string_ascii_utf_functions
4142
StringAsciiUTFFunctionBenchmarks.cpp)
42-
target_link_libraries(velox_functions_benchmarks_string_ascii_utf_functions
43+
target_link_libraries(
44+
velox_functions_prestosql_benchmarks_string_ascii_utf_functions
45+
${BENCHMARK_DEPENDENCIES})
46+
47+
add_executable(velox_functions_prestosql_benchmarks_not NotBenchmark.cpp)
48+
target_link_libraries(velox_functions_prestosql_benchmarks_not
4349
${BENCHMARK_DEPENDENCIES})
4450

45-
add_executable(velox_functions_benchmarks_not NotBenchmark.cpp)
46-
target_link_libraries(velox_functions_benchmarks_not ${BENCHMARK_DEPENDENCIES})
51+
add_executable(velox_functions_prestosql_benchmarks_date_time
52+
DateTimeBenchmark.cpp)
53+
target_link_libraries(velox_functions_prestosql_benchmarks_date_time
54+
${BENCHMARK_DEPENDENCIES})
4755

48-
add_executable(velox_functions_benchmarks_date_time DateTimeBenchmark.cpp)
49-
target_link_libraries(velox_functions_benchmarks_date_time
56+
add_executable(velox_functions_prestosql_benchmarks_bitwise
57+
BitwiseBenchmark.cpp)
58+
target_link_libraries(velox_functions_prestosql_benchmarks_bitwise
5059
${BENCHMARK_DEPENDENCIES})
5160

52-
add_executable(velox_functions_benchmarks_bitwise BitwiseBenchmark.cpp)
53-
target_link_libraries(velox_functions_benchmarks_bitwise
61+
add_executable(velox_functions_prestosql_benchmarks_in InBenchmark.cpp)
62+
target_link_libraries(velox_functions_prestosql_benchmarks_in
5463
${BENCHMARK_DEPENDENCIES})
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
/*
2+
* Copyright (c) Facebook, Inc. and its affiliates.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
#include <folly/Benchmark.h>
17+
#include <folly/container/F14Set.h>
18+
#include <folly/init/Init.h>
19+
#include "velox/expression/tests/VectorFuzzer.h"
20+
#include "velox/functions/lib/benchmarks/FunctionBenchmarkBase.h"
21+
#include "velox/functions/prestosql/VectorFunctions.h"
22+
23+
using namespace facebook::velox;
24+
using namespace facebook::velox::exec;
25+
using namespace facebook::velox::test;
26+
27+
namespace {
28+
29+
/// Fast implementation of IN (a, b, c,..) using F14FastSet.
30+
VectorPtr fastIn(
31+
const folly::F14FastSet<int32_t>& inSet,
32+
const VectorPtr& data) {
33+
const auto numRows = data->size();
34+
auto result = std::static_pointer_cast<FlatVector<bool>>(
35+
BaseVector::create(BOOLEAN(), numRows, data->pool()));
36+
auto rawResults = result->mutableRawValues<int32_t>();
37+
38+
auto rawData = data->asUnchecked<FlatVector<int32_t>>()->rawValues();
39+
for (auto row = 0; row < numRows; ++row) {
40+
bits::setBit(rawResults, row, inSet.contains(rawData[row]));
41+
}
42+
43+
return result;
44+
}
45+
46+
class InBenchmark : public functions::test::FunctionBenchmarkBase {
47+
public:
48+
InBenchmark() : FunctionBenchmarkBase() {
49+
functions::registerVectorFunctions();
50+
}
51+
52+
RowVectorPtr makeData() {
53+
VectorFuzzer::Options opts;
54+
opts.vectorSize = 1'000;
55+
return vectorMaker_.rowVector(
56+
{VectorFuzzer(opts, pool()).fuzzFlat(INTEGER())});
57+
}
58+
59+
void run(size_t numValues) {
60+
folly::BenchmarkSuspender suspender;
61+
auto data = makeData();
62+
63+
std::ostringstream inList;
64+
inList << "0";
65+
for (auto i = 1; i < numValues; ++i) {
66+
inList << ", " << i * 2;
67+
}
68+
69+
auto sql = fmt::format("c0 IN ({})", inList.str());
70+
auto exprSet = compileExpression(sql, data->type());
71+
suspender.dismiss();
72+
73+
doRun(exprSet, data);
74+
}
75+
76+
void doRun(ExprSet& exprSet, const RowVectorPtr& rowVector) {
77+
int cnt = 0;
78+
for (auto i = 0; i < 1000; i++) {
79+
cnt += evaluate(exprSet, rowVector)->size();
80+
}
81+
folly::doNotOptimizeAway(cnt);
82+
}
83+
84+
void runFast(size_t numValues) {
85+
folly::BenchmarkSuspender suspender;
86+
auto data = makeData();
87+
88+
folly::F14FastSet<int32_t> inSet;
89+
inSet.reserve(numValues);
90+
for (auto i = 0; i < numValues; ++i) {
91+
inSet.insert(i);
92+
}
93+
suspender.dismiss();
94+
95+
doRunFast(inSet, data->childAt(0));
96+
}
97+
98+
void doRunFast(
99+
const folly::F14FastSet<int32_t>& inSet,
100+
const VectorPtr& data) {
101+
int cnt = 0;
102+
for (auto i = 0; i < 1000; i++) {
103+
cnt += fastIn(inSet, data)->size();
104+
}
105+
folly::doNotOptimizeAway(cnt);
106+
}
107+
};
108+
109+
BENCHMARK(fastIn) {
110+
InBenchmark benchmark;
111+
benchmark.runFast(10);
112+
}
113+
114+
BENCHMARK_RELATIVE(in) {
115+
InBenchmark benchmark;
116+
benchmark.run(10);
117+
}
118+
119+
BENCHMARK(fastIn1K) {
120+
InBenchmark benchmark;
121+
benchmark.runFast(1'000);
122+
}
123+
124+
BENCHMARK_RELATIVE(in1K) {
125+
InBenchmark benchmark;
126+
benchmark.run(1'000);
127+
}
128+
129+
} // namespace
130+
131+
int main(int /*argc*/, char** /*argv*/) {
132+
folly::runBenchmarks();
133+
return 0;
134+
}

0 commit comments

Comments
 (0)