1 // Licensed to the Apache Software Foundation (ASF) under one
2 // or more contributor license agreements. See the NOTICE file
3 // distributed with this work for additional information
4 // regarding copyright ownership. The ASF licenses this file
5 // to you under the Apache License, Version 2.0 (the
6 // "License"); you may not use this file except in compliance
7 // with the License. You may obtain a copy of the License at
9 // http://www.apache.org/licenses/LICENSE-2.0
11 // Unless required by applicable law or agreed to in writing,
12 // software distributed under the License is distributed on an
13 // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 // KIND, either express or implied. See the License for the
15 // specific language governing permissions and limitations
26 #include <benchmark/benchmark.h>
28 #include "arrow/testing/util.h"
29 #include "arrow/util/logging.h"
30 #include "arrow/util/macros.h"
31 #include "arrow/util/small_vector.h"
39 T
ValueInitializer(int seed
);
42 int ValueInitializer
<int>() {
46 int ValueInitializer
<int>(int seed
) {
51 std::string ValueInitializer
<std::string
>() {
55 std::string ValueInitializer
<std::string
>(int seed
) {
56 return std::string("x", seed
& 0x3f); // avoid making string too long
60 std::shared_ptr
<int> ValueInitializer
<std::shared_ptr
<int>>() {
61 return std::make_shared
<int>(42);
64 std::shared_ptr
<int> ValueInitializer
<std::shared_ptr
<int>>(int seed
) {
65 return std::make_shared
<int>(seed
);
68 template <typename Vector
>
69 ARROW_NOINLINE
int64_t ConsumeVector(Vector v
) {
70 return reinterpret_cast<intptr_t>(v
.data());
73 template <typename Vector
>
74 ARROW_NOINLINE
int64_t IngestVector(const Vector
& v
) {
75 return reinterpret_cast<intptr_t>(v
.data());
78 // With ARROW_NOINLINE, try to make sure the number of items is not constant-propagated
79 template <typename Vector
>
80 ARROW_NOINLINE
void BenchmarkMoveVector(benchmark::State
& state
, Vector vec
) {
81 constexpr int kNumIters
= 1000;
83 for (auto _
: state
) {
85 for (int i
= 0; i
< kNumIters
; ++i
) {
86 Vector
tmp(std::move(vec
));
87 dummy
+= IngestVector(tmp
);
90 benchmark::DoNotOptimize(dummy
);
93 state
.SetItemsProcessed(state
.iterations() * kNumIters
* 2);
96 template <typename Vector
>
97 void MoveEmptyVector(benchmark::State
& state
) {
98 BenchmarkMoveVector(state
, Vector
{});
101 template <typename Vector
>
102 void MoveShortVector(benchmark::State
& state
) {
103 using T
= typename
Vector::value_type
;
104 constexpr int kSize
= 3;
105 const auto initializer
= ValueInitializer
<T
>();
107 BenchmarkMoveVector(state
, Vector(kSize
, initializer
));
110 template <typename Vector
>
111 void CopyEmptyVector(benchmark::State
& state
) {
112 constexpr int kNumIters
= 1000;
116 for (auto _
: state
) {
118 for (int i
= 0; i
< kNumIters
; ++i
) {
119 dummy
+= ConsumeVector(vec
);
121 benchmark::DoNotOptimize(dummy
);
124 state
.SetItemsProcessed(state
.iterations() * kNumIters
);
127 template <typename Vector
>
128 void CopyShortVector(benchmark::State
& state
) {
129 constexpr int kSize
= 3;
130 constexpr int kNumIters
= 1000;
132 const Vector
vec(kSize
);
134 for (auto _
: state
) {
136 for (int i
= 0; i
< kNumIters
; ++i
) {
137 dummy
+= ConsumeVector(vec
);
139 benchmark::DoNotOptimize(dummy
);
142 state
.SetItemsProcessed(state
.iterations() * kNumIters
);
145 // With ARROW_NOINLINE, try to make sure the number of items is not constant-propagated
146 template <typename Vector
>
147 ARROW_NOINLINE
void BenchmarkConstructFromStdVector(benchmark::State
& state
,
149 using T
= typename
Vector::value_type
;
150 constexpr int kNumIters
= 1000;
151 const std::vector
<T
> src(nitems
, ValueInitializer
<T
>());
153 for (auto _
: state
) {
155 for (int i
= 0; i
< kNumIters
; ++i
) {
157 dummy
+= IngestVector(vec
);
159 benchmark::DoNotOptimize(dummy
);
162 state
.SetItemsProcessed(state
.iterations() * kNumIters
);
165 template <typename Vector
>
166 void ConstructFromEmptyStdVector(benchmark::State
& state
) {
167 BenchmarkConstructFromStdVector
<Vector
>(state
, 0);
170 template <typename Vector
>
171 void ConstructFromShortStdVector(benchmark::State
& state
) {
172 BenchmarkConstructFromStdVector
<Vector
>(state
, 3);
175 // With ARROW_NOINLINE, try to make sure the number of items is not constant-propagated
176 template <typename Vector
>
177 ARROW_NOINLINE
void BenchmarkVectorPushBack(benchmark::State
& state
, const int nitems
) {
178 using T
= typename
Vector::value_type
;
179 constexpr int kNumIters
= 1000;
181 ARROW_CHECK_LE(static_cast<size_t>(nitems
), Vector
{}.max_size());
183 for (auto _
: state
) {
185 for (int i
= 0; i
< kNumIters
; ++i
) {
188 for (int j
= 0; j
< nitems
; ++j
) {
189 vec
.push_back(ValueInitializer
<T
>(j
));
191 dummy
+= reinterpret_cast<intptr_t>(vec
.data());
192 benchmark::ClobberMemory();
194 benchmark::DoNotOptimize(dummy
);
197 state
.SetItemsProcessed(state
.iterations() * kNumIters
* nitems
);
200 template <typename Vector
>
201 void ShortVectorPushBack(benchmark::State
& state
) {
202 BenchmarkVectorPushBack
<Vector
>(state
, 3);
205 template <typename Vector
>
206 void LongVectorPushBack(benchmark::State
& state
) {
207 BenchmarkVectorPushBack
<Vector
>(state
, 100);
210 // With ARROW_NOINLINE, try to make sure the source data is not constant-propagated
211 // (we could also use random data)
212 template <typename Vector
, typename T
= typename
Vector::value_type
>
213 ARROW_NOINLINE
void BenchmarkShortVectorInsert(benchmark::State
& state
,
214 const std::vector
<T
>& src
) {
215 constexpr int kNumIters
= 1000;
217 for (auto _
: state
) {
219 for (int i
= 0; i
< kNumIters
; ++i
) {
222 vec
.insert(vec
.begin(), src
.begin(), src
.begin() + 2);
223 vec
.insert(vec
.begin(), src
.begin() + 2, src
.end());
224 dummy
+= reinterpret_cast<intptr_t>(vec
.data());
225 benchmark::ClobberMemory();
227 benchmark::DoNotOptimize(dummy
);
230 state
.SetItemsProcessed(state
.iterations() * kNumIters
* 4);
233 template <typename Vector
>
234 void ShortVectorInsert(benchmark::State
& state
) {
235 using T
= typename
Vector::value_type
;
236 const std::vector
<T
> src(4, ValueInitializer
<T
>());
237 BenchmarkShortVectorInsert
<Vector
>(state
, src
);
240 template <typename Vector
>
241 ARROW_NOINLINE
void BenchmarkVectorInsertAtEnd(benchmark::State
& state
,
243 using T
= typename
Vector::value_type
;
244 constexpr int kNumIters
= 1000;
246 ARROW_CHECK_LE(static_cast<size_t>(nitems
), Vector
{}.max_size());
247 ARROW_CHECK_EQ(nitems
% 2, 0);
250 for (int j
= 0; j
< nitems
/ 2; ++j
) {
251 src
.push_back(ValueInitializer
<T
>(j
));
254 for (auto _
: state
) {
256 for (int i
= 0; i
< kNumIters
; ++i
) {
259 vec
.insert(vec
.end(), src
.begin(), src
.end());
260 vec
.insert(vec
.end(), src
.begin(), src
.end());
261 dummy
+= reinterpret_cast<intptr_t>(vec
.data());
262 benchmark::ClobberMemory();
264 benchmark::DoNotOptimize(dummy
);
267 state
.SetItemsProcessed(state
.iterations() * kNumIters
* nitems
);
270 template <typename Vector
>
271 void ShortVectorInsertAtEnd(benchmark::State
& state
) {
272 BenchmarkVectorInsertAtEnd
<Vector
>(state
, 4);
275 template <typename Vector
>
276 void LongVectorInsertAtEnd(benchmark::State
& state
) {
277 BenchmarkVectorInsertAtEnd
<Vector
>(state
, 100);
280 #define SHORT_VECTOR_BENCHMARKS(VEC_TYPE_FACTORY) \
281 BENCHMARK_TEMPLATE(MoveEmptyVector, VEC_TYPE_FACTORY(int)); \
282 BENCHMARK_TEMPLATE(MoveEmptyVector, VEC_TYPE_FACTORY(std::string)); \
283 BENCHMARK_TEMPLATE(MoveEmptyVector, VEC_TYPE_FACTORY(std::shared_ptr<int>)); \
284 BENCHMARK_TEMPLATE(MoveShortVector, VEC_TYPE_FACTORY(int)); \
285 BENCHMARK_TEMPLATE(MoveShortVector, VEC_TYPE_FACTORY(std::string)); \
286 BENCHMARK_TEMPLATE(MoveShortVector, VEC_TYPE_FACTORY(std::shared_ptr<int>)); \
287 BENCHMARK_TEMPLATE(CopyEmptyVector, VEC_TYPE_FACTORY(int)); \
288 BENCHMARK_TEMPLATE(CopyEmptyVector, VEC_TYPE_FACTORY(std::string)); \
289 BENCHMARK_TEMPLATE(CopyEmptyVector, VEC_TYPE_FACTORY(std::shared_ptr<int>)); \
290 BENCHMARK_TEMPLATE(CopyShortVector, VEC_TYPE_FACTORY(int)); \
291 BENCHMARK_TEMPLATE(CopyShortVector, VEC_TYPE_FACTORY(std::string)); \
292 BENCHMARK_TEMPLATE(CopyShortVector, VEC_TYPE_FACTORY(std::shared_ptr<int>)); \
293 BENCHMARK_TEMPLATE(ConstructFromEmptyStdVector, VEC_TYPE_FACTORY(int)); \
294 BENCHMARK_TEMPLATE(ConstructFromEmptyStdVector, VEC_TYPE_FACTORY(std::string)); \
295 BENCHMARK_TEMPLATE(ConstructFromEmptyStdVector, \
296 VEC_TYPE_FACTORY(std::shared_ptr<int>)); \
297 BENCHMARK_TEMPLATE(ConstructFromShortStdVector, VEC_TYPE_FACTORY(int)); \
298 BENCHMARK_TEMPLATE(ConstructFromShortStdVector, VEC_TYPE_FACTORY(std::string)); \
299 BENCHMARK_TEMPLATE(ConstructFromShortStdVector, \
300 VEC_TYPE_FACTORY(std::shared_ptr<int>)); \
301 BENCHMARK_TEMPLATE(ShortVectorPushBack, VEC_TYPE_FACTORY(int)); \
302 BENCHMARK_TEMPLATE(ShortVectorPushBack, VEC_TYPE_FACTORY(std::string)); \
303 BENCHMARK_TEMPLATE(ShortVectorPushBack, VEC_TYPE_FACTORY(std::shared_ptr<int>)); \
304 BENCHMARK_TEMPLATE(ShortVectorInsert, VEC_TYPE_FACTORY(int)); \
305 BENCHMARK_TEMPLATE(ShortVectorInsert, VEC_TYPE_FACTORY(std::string)); \
306 BENCHMARK_TEMPLATE(ShortVectorInsert, VEC_TYPE_FACTORY(std::shared_ptr<int>)); \
307 BENCHMARK_TEMPLATE(ShortVectorInsertAtEnd, VEC_TYPE_FACTORY(int)); \
308 BENCHMARK_TEMPLATE(ShortVectorInsertAtEnd, VEC_TYPE_FACTORY(std::string)); \
309 BENCHMARK_TEMPLATE(ShortVectorInsertAtEnd, VEC_TYPE_FACTORY(std::shared_ptr<int>));
311 #define LONG_VECTOR_BENCHMARKS(VEC_TYPE_FACTORY) \
312 BENCHMARK_TEMPLATE(LongVectorPushBack, VEC_TYPE_FACTORY(int)); \
313 BENCHMARK_TEMPLATE(LongVectorPushBack, VEC_TYPE_FACTORY(std::string)); \
314 BENCHMARK_TEMPLATE(LongVectorPushBack, VEC_TYPE_FACTORY(std::shared_ptr<int>)); \
315 BENCHMARK_TEMPLATE(LongVectorInsertAtEnd, VEC_TYPE_FACTORY(int)); \
316 BENCHMARK_TEMPLATE(LongVectorInsertAtEnd, VEC_TYPE_FACTORY(std::string)); \
317 BENCHMARK_TEMPLATE(LongVectorInsertAtEnd, VEC_TYPE_FACTORY(std::shared_ptr<int>));
319 // NOTE: the macro name below (STD_VECTOR etc.) is reflected in the
320 // benchmark name, so use descriptive names.
322 #ifdef ARROW_WITH_BENCHMARKS_REFERENCE
324 #define STD_VECTOR(T) std::vector<T>
325 SHORT_VECTOR_BENCHMARKS(STD_VECTOR
);
326 LONG_VECTOR_BENCHMARKS(STD_VECTOR
);
331 #define STATIC_VECTOR(T) StaticVector<T, 4>
332 SHORT_VECTOR_BENCHMARKS(STATIC_VECTOR
);
335 #define SMALL_VECTOR(T) SmallVector<T, 4>
336 SHORT_VECTOR_BENCHMARKS(SMALL_VECTOR
);
337 LONG_VECTOR_BENCHMARKS(SMALL_VECTOR
);
340 #undef SHORT_VECTOR_BENCHMARKS
341 #undef LONG_VECTOR_BENCHMARKS
343 } // namespace internal