-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Avoid unconditional make_heap for priority_queue::push_range
#4025
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
68b5436
38a1ef4
b8dc640
3f32401
2305bca
b676d18
5b907b7
959d881
d5ffbe5
6fe8eed
28732ae
234f0f3
bef9286
a66b992
9db2be4
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,89 @@ | ||
| // Copyright (c) Microsoft Corporation. | ||
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
|
|
||
| #include <algorithm> | ||
| #include <benchmark/benchmark.h> | ||
| #include <cstddef> | ||
| #include <cstdint> | ||
| #include <cstdio> | ||
| #include <queue> | ||
| #include <random> | ||
| #include <span> | ||
| #include <string> | ||
| #include <string_view> | ||
| #include <vector> | ||
| using namespace std; | ||
|
|
||
| namespace { | ||
| constexpr size_t vec_size = 10'000; | ||
|
|
||
| template <class T, class Fn> | ||
| auto create_vec(Fn transformation) { | ||
| vector<T> vec(vec_size); | ||
| for (mt19937_64 rnd(1); auto& e : vec) { | ||
| e = transformation(rnd()); | ||
| } | ||
| return vec; | ||
| } | ||
|
|
||
| template <class T> | ||
| T cast_to(uint64_t val) { | ||
| return static_cast<T>(val); | ||
| } | ||
|
|
||
| const auto vec_u8 = create_vec<uint8_t>(cast_to<uint8_t>); | ||
| const auto vec_u16 = create_vec<uint16_t>(cast_to<uint16_t>); | ||
| const auto vec_u32 = create_vec<uint32_t>(cast_to<uint32_t>); | ||
| const auto vec_u64 = create_vec<uint64_t>(cast_to<uint64_t>); | ||
| const auto vec_float = create_vec<float>(cast_to<float>); | ||
| const auto vec_double = create_vec<double>(cast_to<double>); | ||
|
|
||
| const auto vec_str = create_vec<string>([](uint64_t val) { return to_string(static_cast<uint32_t>(val)); }); | ||
| const auto vec_wstr = create_vec<wstring>([](uint64_t val) { return to_wstring(static_cast<uint32_t>(val)); }); | ||
|
|
||
| template <class T, const auto& Data> | ||
| void BM_push_range(benchmark::State& state) { | ||
| const size_t frag_size = static_cast<size_t>(state.range(0)); | ||
|
|
||
| for (auto _ : state) { | ||
| priority_queue<T> que; | ||
| span spn{Data}; | ||
|
|
||
| while (!spn.empty()) { | ||
| const size_t take_size = min(spn.size(), frag_size); | ||
| que.push_range(spn.first(take_size)); | ||
| spn = spn.subspan(take_size); | ||
| } | ||
| benchmark::DoNotOptimize(que); | ||
| } | ||
| } | ||
|
|
||
| template <size_t L> | ||
| void putln(const benchmark::State&) { | ||
| static bool b = [] { | ||
| puts(""); | ||
| return true; | ||
| }(); | ||
| } | ||
| } // namespace | ||
|
|
||
| #define TEST_PUSH_RANGE(T, source) \ | ||
| BENCHMARK(BM_push_range<T, source>) \ | ||
| ->Setup(putln<__LINE__>) \ | ||
| ->RangeMultiplier(100) \ | ||
| ->Range(1, vec_size) \ | ||
| ->Arg(vec_size / 2 + 1); | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
|
|
||
| TEST_PUSH_RANGE(uint8_t, vec_u8); | ||
|
StephanTLavavej marked this conversation as resolved.
|
||
| TEST_PUSH_RANGE(uint16_t, vec_u16); | ||
| TEST_PUSH_RANGE(uint32_t, vec_u32); | ||
| TEST_PUSH_RANGE(uint64_t, vec_u64); | ||
| TEST_PUSH_RANGE(float, vec_float); | ||
| TEST_PUSH_RANGE(double, vec_double); | ||
|
|
||
| TEST_PUSH_RANGE(string_view, vec_str); | ||
|
StephanTLavavej marked this conversation as resolved.
|
||
| TEST_PUSH_RANGE(string, vec_str); | ||
| TEST_PUSH_RANGE(wstring_view, vec_wstr); | ||
| TEST_PUSH_RANGE(wstring, vec_wstr); | ||
|
|
||
| BENCHMARK_MAIN(); | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -541,7 +541,8 @@ struct less_equal<void> { | |
| template <class _Fx> | ||
| struct _Ref_fn { // pass function object by value as a reference | ||
| template <class... _Args> | ||
| constexpr decltype(auto) operator()(_Args&&... _Vals) { // forward function call operator | ||
| constexpr decltype(auto) operator()(_Args&&... _Vals) noexcept( | ||
| _Select_invoke_traits<_Fx&, _Args...>::_Is_nothrow_invocable::value) { // forward function call operator | ||
|
Comment on lines
-544
to
+545
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No change required - I don't have data to back up the claim - but there's a lot of expensive SFINAE in template <class _Fx, bool = is_member_pointer_v<_Fx>>
struct _Ref_fn { // pass function object by value as a reference
template <class... _Args>
constexpr decltype(auto) operator()(_Args&&... _Vals) noexcept(
noexcept(_STD invoke(_Fn, _STD forward<_Args>(_Vals)...))) {
return _STD invoke(_Fn, _STD forward<_Args>(_Vals)...);
}
_Fx& _Fn;
};
template <class _Fx>
struct _Ref_fn<_Fx, false> {
template <class... _Args>
constexpr decltype(auto) operator()(_Args&&... _Vals) noexcept(noexcept(_Fn(_STD forward<_Args>(_Vals)...))) {
return _Fn(_STD forward<_Args>(_Vals)...);
}
_Fx& _Fn;
}; |
||
| if constexpr (is_member_pointer_v<_Fx>) { | ||
| return _STD invoke(_Fn, _STD forward<_Args>(_Vals)...); | ||
| } else { | ||
|
|
||


Uh oh!
There was an error while loading. Please reload this page.