- b9a479321581cd0293f124041bf5c06f456afec1 Adds exception safety tests for absl::make_unique<T>(...) by Abseil Team <absl-team@google.com>
- 78c61364007f6ab66155c151d0061bbec89c3dbd Update variadic visitation to use a switch statement when... by Matt Calabrese <calabrese@google.com> - b62eb9546087e0001307a741fcdf023b2d156966 Merge GitHub PR #130 - Add MIPS support to GetProgramCoun... by Derek Mauro <dmauro@google.com> - 09ab5739de33c8f1bebab2bb70bf7d4331348f05 Update ABSL_ASSERT to silence clang-tidy warnings about c... by Matt Calabrese <calabrese@google.com> - e73ee389ce8fe1a90738973c219ebbb19bb389f3 Update unary visitation to use a switch statement when th... by Matt Calabrese <calabrese@google.com> - c8734ccf475b856c95220f21a5ec4f44302cb5ce Work around a MSVC bug for absl::variant, by making `Acce... by Xiaoyi Zhang <zhangxy@google.com> GitOrigin-RevId: b9a479321581cd0293f124041bf5c06f456afec1 Change-Id: Idb6fc906087c0a4e6fc5c75a391c7f73101c613epull/134/head
parent
e5be80532b
commit
eb686c069f
8 changed files with 610 additions and 40 deletions
@ -0,0 +1,49 @@ |
||||
// Copyright 2018 The Abseil Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "absl/memory/memory.h" |
||||
|
||||
#include "gtest/gtest.h" |
||||
#include "absl/base/internal/exception_safety_testing.h" |
||||
|
||||
namespace absl { |
||||
namespace { |
||||
|
||||
using Thrower = ::testing::ThrowingValue<>; |
||||
|
||||
TEST(MakeUnique, CheckForLeaks) { |
||||
constexpr int kValue = 321; |
||||
constexpr size_t kLength = 10; |
||||
auto tester = testing::MakeExceptionSafetyTester() |
||||
.WithInitialValue(Thrower(kValue)) |
||||
// Ensures make_unique does not modify the input. The real
|
||||
// test, though, is ConstructorTracker checking for leaks.
|
||||
.WithInvariants(testing::strong_guarantee); |
||||
|
||||
EXPECT_TRUE(tester.Test([](Thrower* thrower) { |
||||
static_cast<void>(absl::make_unique<Thrower>(*thrower)); |
||||
})); |
||||
|
||||
EXPECT_TRUE(tester.Test([](Thrower* thrower) { |
||||
static_cast<void>(absl::make_unique<Thrower>(std::move(*thrower))); |
||||
})); |
||||
|
||||
// Test T[n] overload
|
||||
EXPECT_TRUE(tester.Test([&](Thrower*) { |
||||
static_cast<void>(absl::make_unique<Thrower[]>(kLength)); |
||||
})); |
||||
} |
||||
|
||||
} // namespace
|
||||
} // namespace absl
|
@ -0,0 +1,220 @@ |
||||
// Copyright 2017 The Abseil Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Unit tests for the variant template. The 'is' and 'IsEmpty' methods
|
||||
// of variant are not explicitly tested because they are used repeatedly
|
||||
// in building other tests. All other public variant methods should have
|
||||
// explicit tests.
|
||||
|
||||
#include "absl/types/variant.h" |
||||
|
||||
#include <cstddef> |
||||
#include <cstdlib> |
||||
#include <string> |
||||
#include <tuple> |
||||
|
||||
#include "benchmark/benchmark.h" |
||||
#include "absl/utility/utility.h" |
||||
|
||||
namespace absl { |
||||
namespace { |
||||
|
||||
template <std::size_t I> |
||||
struct VariantAlternative { |
||||
char member; |
||||
}; |
||||
|
||||
template <class Indices> |
||||
struct VariantOfAlternativesImpl; |
||||
|
||||
template <std::size_t... Indices> |
||||
struct VariantOfAlternativesImpl<absl::index_sequence<Indices...>> { |
||||
using type = absl::variant<VariantAlternative<Indices>...>; |
||||
}; |
||||
|
||||
template <std::size_t NumAlternatives> |
||||
using VariantOfAlternatives = typename VariantOfAlternativesImpl< |
||||
absl::make_index_sequence<NumAlternatives>>::type; |
||||
|
||||
struct Empty {}; |
||||
|
||||
template <class... T> |
||||
void Ignore(T...) noexcept {} |
||||
|
||||
template <class T> |
||||
Empty DoNotOptimizeAndReturnEmpty(T&& arg) noexcept { |
||||
benchmark::DoNotOptimize(arg); |
||||
return {}; |
||||
} |
||||
|
||||
struct VisitorApplier { |
||||
struct Visitor { |
||||
template <class... T> |
||||
void operator()(T&&... args) const noexcept { |
||||
Ignore(DoNotOptimizeAndReturnEmpty(args)...); |
||||
} |
||||
}; |
||||
|
||||
template <class... Vars> |
||||
void operator()(const Vars&... vars) const noexcept { |
||||
absl::visit(Visitor(), vars...); |
||||
} |
||||
}; |
||||
|
||||
template <std::size_t NumIndices, std::size_t CurrIndex = NumIndices - 1> |
||||
struct MakeWithIndex { |
||||
using Variant = VariantOfAlternatives<NumIndices>; |
||||
|
||||
static Variant Run(std::size_t index) { |
||||
return index == CurrIndex |
||||
? Variant(absl::in_place_index_t<CurrIndex>()) |
||||
: MakeWithIndex<NumIndices, CurrIndex - 1>::Run(index); |
||||
} |
||||
}; |
||||
|
||||
template <std::size_t NumIndices> |
||||
struct MakeWithIndex<NumIndices, 0> { |
||||
using Variant = VariantOfAlternatives<NumIndices>; |
||||
|
||||
static Variant Run(std::size_t /*index*/) { return Variant(); } |
||||
}; |
||||
|
||||
template <std::size_t NumIndices, class Dimensions> |
||||
struct MakeVariantTuple; |
||||
|
||||
template <class T, std::size_t /*I*/> |
||||
using always_t = T; |
||||
|
||||
template <std::size_t NumIndices> |
||||
VariantOfAlternatives<NumIndices> MakeVariant(std::size_t dimension, |
||||
std::size_t index) { |
||||
return dimension == 0 |
||||
? MakeWithIndex<NumIndices>::Run(index % NumIndices) |
||||
: MakeVariant<NumIndices>(dimension - 1, index / NumIndices); |
||||
} |
||||
|
||||
template <std::size_t NumIndices, std::size_t... Dimensions> |
||||
struct MakeVariantTuple<NumIndices, absl::index_sequence<Dimensions...>> { |
||||
using VariantTuple = |
||||
std::tuple<always_t<VariantOfAlternatives<NumIndices>, Dimensions>...>; |
||||
|
||||
static VariantTuple Run(int index) { |
||||
return std::make_tuple(MakeVariant<NumIndices>(Dimensions, index)...); |
||||
} |
||||
}; |
||||
|
||||
constexpr std::size_t integral_pow(std::size_t base, std::size_t power) { |
||||
return power == 0 ? 1 : base * integral_pow(base, power - 1); |
||||
} |
||||
|
||||
template <std::size_t End, std::size_t I = 0> |
||||
struct VisitTestBody { |
||||
template <class Vars, class State> |
||||
static bool Run(Vars& vars, State& state) { |
||||
if (state.KeepRunning()) { |
||||
absl::apply(VisitorApplier(), vars[I]); |
||||
return VisitTestBody<End, I + 1>::Run(vars, state); |
||||
} |
||||
return false; |
||||
} |
||||
}; |
||||
|
||||
template <std::size_t End> |
||||
struct VisitTestBody<End, End> { |
||||
template <class Vars, class State> |
||||
static bool Run(Vars& /*vars*/, State& /*state*/) { |
||||
return true; |
||||
} |
||||
}; |
||||
|
||||
// Visit operations where branch prediction is likely to give a boost.
|
||||
template <std::size_t NumIndices, std::size_t NumDimensions = 1> |
||||
void BM_RedundantVisit(benchmark::State& state) { |
||||
auto vars = |
||||
MakeVariantTuple<NumIndices, absl::make_index_sequence<NumDimensions>>:: |
||||
Run(static_cast<std::size_t>(state.range(0))); |
||||
|
||||
for (auto _ : state) { // NOLINT
|
||||
benchmark::DoNotOptimize(vars); |
||||
absl::apply(VisitorApplier(), vars); |
||||
} |
||||
} |
||||
|
||||
// Visit operations where branch prediction is unlikely to give a boost.
|
||||
template <std::size_t NumIndices, std::size_t NumDimensions = 1> |
||||
void BM_Visit(benchmark::State& state) { |
||||
constexpr std::size_t num_possibilities = |
||||
integral_pow(NumIndices, NumDimensions); |
||||
|
||||
using VariantTupleMaker = |
||||
MakeVariantTuple<NumIndices, absl::make_index_sequence<NumDimensions>>; |
||||
using Tuple = typename VariantTupleMaker::VariantTuple; |
||||
|
||||
Tuple vars[num_possibilities]; |
||||
for (std::size_t i = 0; i < num_possibilities; ++i) |
||||
vars[i] = VariantTupleMaker::Run(i); |
||||
|
||||
while (VisitTestBody<num_possibilities>::Run(vars, state)) { |
||||
} |
||||
} |
||||
|
||||
// Visitation
|
||||
// Each visit is on a different variant with a different active alternative)
|
||||
|
||||
// Unary visit
|
||||
BENCHMARK_TEMPLATE(BM_Visit, 1); |
||||
BENCHMARK_TEMPLATE(BM_Visit, 2); |
||||
BENCHMARK_TEMPLATE(BM_Visit, 3); |
||||
BENCHMARK_TEMPLATE(BM_Visit, 4); |
||||
BENCHMARK_TEMPLATE(BM_Visit, 5); |
||||
BENCHMARK_TEMPLATE(BM_Visit, 6); |
||||
BENCHMARK_TEMPLATE(BM_Visit, 7); |
||||
BENCHMARK_TEMPLATE(BM_Visit, 8); |
||||
BENCHMARK_TEMPLATE(BM_Visit, 16); |
||||
BENCHMARK_TEMPLATE(BM_Visit, 32); |
||||
BENCHMARK_TEMPLATE(BM_Visit, 64); |
||||
|
||||
// Binary visit
|
||||
BENCHMARK_TEMPLATE(BM_Visit, 1, 2); |
||||
BENCHMARK_TEMPLATE(BM_Visit, 2, 2); |
||||
BENCHMARK_TEMPLATE(BM_Visit, 3, 2); |
||||
BENCHMARK_TEMPLATE(BM_Visit, 4, 2); |
||||
BENCHMARK_TEMPLATE(BM_Visit, 5, 2); |
||||
|
||||
// Ternary visit
|
||||
BENCHMARK_TEMPLATE(BM_Visit, 1, 3); |
||||
BENCHMARK_TEMPLATE(BM_Visit, 2, 3); |
||||
BENCHMARK_TEMPLATE(BM_Visit, 3, 3); |
||||
|
||||
// Quaternary visit
|
||||
BENCHMARK_TEMPLATE(BM_Visit, 1, 4); |
||||
BENCHMARK_TEMPLATE(BM_Visit, 2, 4); |
||||
|
||||
// Redundant Visitation
|
||||
// Each visit consistently has the same alternative active
|
||||
|
||||
// Unary visit
|
||||
BENCHMARK_TEMPLATE(BM_RedundantVisit, 1)->Arg(0); |
||||
BENCHMARK_TEMPLATE(BM_RedundantVisit, 2)->DenseRange(0, 1); |
||||
BENCHMARK_TEMPLATE(BM_RedundantVisit, 8)->DenseRange(0, 7); |
||||
|
||||
// Binary visit
|
||||
BENCHMARK_TEMPLATE(BM_RedundantVisit, 1, 2)->Arg(0); |
||||
BENCHMARK_TEMPLATE(BM_RedundantVisit, 2, 2) |
||||
->DenseRange(0, integral_pow(2, 2) - 1); |
||||
BENCHMARK_TEMPLATE(BM_RedundantVisit, 4, 2) |
||||
->DenseRange(0, integral_pow(4, 2) - 1); |
||||
|
||||
} // namespace
|
||||
} // namespace absl
|
Loading…
Reference in new issue