- abacaab4b11a69dd4db627bd183571d7cabb8def Refinement to previous time.h edit (in this same github p... by Greg Falcon <gfalcon@google.com>
- 64db19b773134c6c8004e3b23c9ca892efbf8bae Move SpinLock's adaptive spin count computation from a st... by Derek Mauro <dmauro@google.com> - 6f9533fb44a52485a7c2bbb9b4efc7bf8d6c359a Import of CCTZ from GitHub. by Abseil Team <absl-team@google.com> - a211d7255c986e8dd4ceada362c0d054a6a1969a Cleanup exception flags by Abseil Team <absl-team@google.com> - babdb29c590126fe9bba5229fe91034b5b5c358a Release time benchmarks. by Alex Strelnikov <strel@google.com> - 5803b32a3ff123d1fb57a0c471d199c818357c9f Release memutil microbenchmarks. by Alex Strelnikov <strel@google.com> - 5357d4890d30e80c53beb05af32500fb20e9402b Add parens around expansion of ABSL_PREDICT_{FALSE,TRUE} ... by Abseil Team <absl-team@google.com> - 32023f61a239a5f6b1c59e577bfe81b179bbcd2d Reformat build rule tag. by Alex Strelnikov <strel@google.com> - 833758ecf2b0cf7a42bbd50b5b127e416425c168 Release uint128 microbenchmarks. by Alex Strelnikov <strel@google.com> - c115a9bca1f944b90fdc78a56b2de176466b124f Disambiguate bitwise-not of size_type by Abseil Team <absl-team@google.com> - f6905f5b5f6e425792de646edafde440548d9346 Updates ConstructorTracker and TrackedObjects with 1) a m... by Abseil Team <absl-team@google.com> - 147c553bdd5d2db20a38f75c4d1ef973d6c709c5 Changes the absl::Duration factory functions to disallow ... by Greg Miller <jgm@google.com> - dba2b96d11b5264546b283ba452f2de1303b0f07 White space fix by Alex Strelnikov <strel@google.com> GitOrigin-RevId: abacaab4b11a69dd4db627bd183571d7cabb8def Change-Id: I6fa34f20d0b2f898e7b5475a603111413bb80a67pull/130/head
parent
7aacab8ae0
commit
92020a042c
22 changed files with 1804 additions and 278 deletions
@ -0,0 +1,221 @@ |
||||
// 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.
|
||||
|
||||
#include "absl/numeric/int128.h" |
||||
|
||||
#include <algorithm> |
||||
#include <cstdint> |
||||
#include <random> |
||||
#include <vector> |
||||
|
||||
#include "benchmark/benchmark.h" |
||||
#include "absl/base/config.h" |
||||
|
||||
namespace { |
||||
|
||||
constexpr size_t kSampleSize = 1000000; |
||||
|
||||
std::mt19937 MakeRandomEngine() { |
||||
std::random_device r; |
||||
std::seed_seq seed({r(), r(), r(), r(), r(), r(), r(), r()}); |
||||
return std::mt19937(seed); |
||||
} |
||||
|
||||
std::vector<std::pair<absl::uint128, absl::uint128>> |
||||
GetRandomClass128SampleUniformDivisor() { |
||||
std::vector<std::pair<absl::uint128, absl::uint128>> values; |
||||
std::mt19937 random = MakeRandomEngine(); |
||||
std::uniform_int_distribution<uint64_t> uniform_uint64; |
||||
values.reserve(kSampleSize); |
||||
for (size_t i = 0; i < kSampleSize; ++i) { |
||||
absl::uint128 a = |
||||
absl::MakeUint128(uniform_uint64(random), uniform_uint64(random)); |
||||
absl::uint128 b = |
||||
absl::MakeUint128(uniform_uint64(random), uniform_uint64(random)); |
||||
values.emplace_back(std::max(a, b), |
||||
std::max(absl::uint128(2), std::min(a, b))); |
||||
} |
||||
return values; |
||||
} |
||||
|
||||
void BM_DivideClass128UniformDivisor(benchmark::State& state) { |
||||
auto values = GetRandomClass128SampleUniformDivisor(); |
||||
while (state.KeepRunningBatch(values.size())) { |
||||
for (const auto& pair : values) { |
||||
benchmark::DoNotOptimize(pair.first / pair.second); |
||||
} |
||||
} |
||||
} |
||||
BENCHMARK(BM_DivideClass128UniformDivisor); |
||||
|
||||
std::vector<std::pair<absl::uint128, uint64_t>> |
||||
GetRandomClass128SampleSmallDivisor() { |
||||
std::vector<std::pair<absl::uint128, uint64_t>> values; |
||||
std::mt19937 random = MakeRandomEngine(); |
||||
std::uniform_int_distribution<uint64_t> uniform_uint64; |
||||
values.reserve(kSampleSize); |
||||
for (size_t i = 0; i < kSampleSize; ++i) { |
||||
absl::uint128 a = |
||||
absl::MakeUint128(uniform_uint64(random), uniform_uint64(random)); |
||||
uint64_t b = std::max(uint64_t{2}, uniform_uint64(random)); |
||||
values.emplace_back(std::max(a, absl::uint128(b)), b); |
||||
} |
||||
return values; |
||||
} |
||||
|
||||
void BM_DivideClass128SmallDivisor(benchmark::State& state) { |
||||
auto values = GetRandomClass128SampleSmallDivisor(); |
||||
while (state.KeepRunningBatch(values.size())) { |
||||
for (const auto& pair : values) { |
||||
benchmark::DoNotOptimize(pair.first / pair.second); |
||||
} |
||||
} |
||||
} |
||||
BENCHMARK(BM_DivideClass128SmallDivisor); |
||||
|
||||
std::vector<std::pair<absl::uint128, absl::uint128>> GetRandomClass128Sample() { |
||||
std::vector<std::pair<absl::uint128, absl::uint128>> values; |
||||
std::mt19937 random = MakeRandomEngine(); |
||||
std::uniform_int_distribution<uint64_t> uniform_uint64; |
||||
values.reserve(kSampleSize); |
||||
for (size_t i = 0; i < kSampleSize; ++i) { |
||||
values.emplace_back( |
||||
absl::MakeUint128(uniform_uint64(random), uniform_uint64(random)), |
||||
absl::MakeUint128(uniform_uint64(random), uniform_uint64(random))); |
||||
} |
||||
return values; |
||||
} |
||||
|
||||
void BM_MultiplyClass128(benchmark::State& state) { |
||||
auto values = GetRandomClass128Sample(); |
||||
while (state.KeepRunningBatch(values.size())) { |
||||
for (const auto& pair : values) { |
||||
benchmark::DoNotOptimize(pair.first * pair.second); |
||||
} |
||||
} |
||||
} |
||||
BENCHMARK(BM_MultiplyClass128); |
||||
|
||||
void BM_AddClass128(benchmark::State& state) { |
||||
auto values = GetRandomClass128Sample(); |
||||
while (state.KeepRunningBatch(values.size())) { |
||||
for (const auto& pair : values) { |
||||
benchmark::DoNotOptimize(pair.first + pair.second); |
||||
} |
||||
} |
||||
} |
||||
BENCHMARK(BM_AddClass128); |
||||
|
||||
#ifdef ABSL_HAVE_INTRINSIC_INT128 |
||||
|
||||
// Some implementations of <random> do not support __int128 when it is
|
||||
// available, so we make our own uniform_int_distribution-like type.
|
||||
class UniformIntDistribution128 { |
||||
public: |
||||
// NOLINTNEXTLINE: mimicking std::uniform_int_distribution API
|
||||
unsigned __int128 operator()(std::mt19937& generator) { |
||||
return (static_cast<unsigned __int128>(dist64_(generator)) << 64) | |
||||
dist64_(generator); |
||||
} |
||||
|
||||
private: |
||||
std::uniform_int_distribution<uint64_t> dist64_; |
||||
}; |
||||
|
||||
std::vector<std::pair<unsigned __int128, unsigned __int128>> |
||||
GetRandomIntrinsic128SampleUniformDivisor() { |
||||
std::vector<std::pair<unsigned __int128, unsigned __int128>> values; |
||||
std::mt19937 random = MakeRandomEngine(); |
||||
UniformIntDistribution128 uniform_uint128; |
||||
values.reserve(kSampleSize); |
||||
for (size_t i = 0; i < kSampleSize; ++i) { |
||||
unsigned __int128 a = uniform_uint128(random); |
||||
unsigned __int128 b = uniform_uint128(random); |
||||
values.emplace_back( |
||||
std::max(a, b), |
||||
std::max(static_cast<unsigned __int128>(2), std::min(a, b))); |
||||
} |
||||
return values; |
||||
} |
||||
|
||||
void BM_DivideIntrinsic128UniformDivisor(benchmark::State& state) { |
||||
auto values = GetRandomIntrinsic128SampleUniformDivisor(); |
||||
while (state.KeepRunningBatch(values.size())) { |
||||
for (const auto& pair : values) { |
||||
benchmark::DoNotOptimize(pair.first / pair.second); |
||||
} |
||||
} |
||||
} |
||||
BENCHMARK(BM_DivideIntrinsic128UniformDivisor); |
||||
|
||||
std::vector<std::pair<unsigned __int128, uint64_t>> |
||||
GetRandomIntrinsic128SampleSmallDivisor() { |
||||
std::vector<std::pair<unsigned __int128, uint64_t>> values; |
||||
std::mt19937 random = MakeRandomEngine(); |
||||
UniformIntDistribution128 uniform_uint128; |
||||
std::uniform_int_distribution<uint64_t> uniform_uint64; |
||||
values.reserve(kSampleSize); |
||||
for (size_t i = 0; i < kSampleSize; ++i) { |
||||
unsigned __int128 a = uniform_uint128(random); |
||||
uint64_t b = std::max(uint64_t{2}, uniform_uint64(random)); |
||||
values.emplace_back(std::max(a, static_cast<unsigned __int128>(b)), b); |
||||
} |
||||
return values; |
||||
} |
||||
|
||||
void BM_DivideIntrinsic128SmallDivisor(benchmark::State& state) { |
||||
auto values = GetRandomIntrinsic128SampleSmallDivisor(); |
||||
while (state.KeepRunningBatch(values.size())) { |
||||
for (const auto& pair : values) { |
||||
benchmark::DoNotOptimize(pair.first / pair.second); |
||||
} |
||||
} |
||||
} |
||||
BENCHMARK(BM_DivideIntrinsic128SmallDivisor); |
||||
|
||||
std::vector<std::pair<unsigned __int128, unsigned __int128>> |
||||
GetRandomIntrinsic128Sample() { |
||||
std::vector<std::pair<unsigned __int128, unsigned __int128>> values; |
||||
std::mt19937 random = MakeRandomEngine(); |
||||
UniformIntDistribution128 uniform_uint128; |
||||
values.reserve(kSampleSize); |
||||
for (size_t i = 0; i < kSampleSize; ++i) { |
||||
values.emplace_back(uniform_uint128(random), uniform_uint128(random)); |
||||
} |
||||
return values; |
||||
} |
||||
|
||||
void BM_MultiplyIntrinsic128(benchmark::State& state) { |
||||
auto values = GetRandomIntrinsic128Sample(); |
||||
while (state.KeepRunningBatch(values.size())) { |
||||
for (const auto& pair : values) { |
||||
benchmark::DoNotOptimize(pair.first * pair.second); |
||||
} |
||||
} |
||||
} |
||||
BENCHMARK(BM_MultiplyIntrinsic128); |
||||
|
||||
void BM_AddIntrinsic128(benchmark::State& state) { |
||||
auto values = GetRandomIntrinsic128Sample(); |
||||
while (state.KeepRunningBatch(values.size())) { |
||||
for (const auto& pair : values) { |
||||
benchmark::DoNotOptimize(pair.first + pair.second); |
||||
} |
||||
} |
||||
} |
||||
BENCHMARK(BM_AddIntrinsic128); |
||||
|
||||
#endif // ABSL_HAVE_INTRINSIC_INT128
|
||||
|
||||
} // namespace
|
@ -0,0 +1,323 @@ |
||||
// 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/strings/internal/memutil.h" |
||||
|
||||
#include <algorithm> |
||||
#include <cstdlib> |
||||
|
||||
#include "benchmark/benchmark.h" |
||||
#include "absl/strings/ascii.h" |
||||
|
||||
// We fill the haystack with aaaaaaaaaaaaaaaaaa...aaaab.
|
||||
// That gives us:
|
||||
// - an easy search: 'b'
|
||||
// - a medium search: 'ab'. That means every letter is a possible match.
|
||||
// - a pathological search: 'aaaaaa.......aaaaab' (half as many a's as haytack)
|
||||
// We benchmark case-sensitive and case-insensitive versions of
|
||||
// three memmem implementations:
|
||||
// - memmem() from memutil.h
|
||||
// - search() from STL
|
||||
// - memmatch(), a custom implementation using memchr and memcmp.
|
||||
// Here are sample results:
|
||||
//
|
||||
// Run on (12 X 3800 MHz CPU s)
|
||||
// CPU Caches:
|
||||
// L1 Data 32K (x6)
|
||||
// L1 Instruction 32K (x6)
|
||||
// L2 Unified 256K (x6)
|
||||
// L3 Unified 15360K (x1)
|
||||
// ----------------------------------------------------------------
|
||||
// Benchmark Time CPU Iterations
|
||||
// ----------------------------------------------------------------
|
||||
// BM_Memmem 3583 ns 3582 ns 196469 2.59966GB/s
|
||||
// BM_MemmemMedium 13743 ns 13742 ns 50901 693.986MB/s
|
||||
// BM_MemmemPathological 13695030 ns 13693977 ns 51 713.133kB/s
|
||||
// BM_Memcasemem 3299 ns 3299 ns 212942 2.82309GB/s
|
||||
// BM_MemcasememMedium 16407 ns 16406 ns 42170 581.309MB/s
|
||||
// BM_MemcasememPathological 17267745 ns 17266030 ns 41 565.598kB/s
|
||||
// BM_Search 1610 ns 1609 ns 431321 5.78672GB/s
|
||||
// BM_SearchMedium 11111 ns 11110 ns 63001 858.414MB/s
|
||||
// BM_SearchPathological 12117390 ns 12116397 ns 58 805.984kB/s
|
||||
// BM_Searchcase 3081 ns 3081 ns 229949 3.02313GB/s
|
||||
// BM_SearchcaseMedium 16003 ns 16001 ns 44170 595.998MB/s
|
||||
// BM_SearchcasePathological 15823413 ns 15821909 ns 44 617.222kB/s
|
||||
// BM_Memmatch 197 ns 197 ns 3584225 47.2951GB/s
|
||||
// BM_MemmatchMedium 52333 ns 52329 ns 13280 182.244MB/s
|
||||
// BM_MemmatchPathological 659799 ns 659727 ns 1058 14.4556MB/s
|
||||
// BM_Memcasematch 5460 ns 5460 ns 127606 1.70586GB/s
|
||||
// BM_MemcasematchMedium 32861 ns 32857 ns 21258 290.248MB/s
|
||||
// BM_MemcasematchPathological 15154243 ns 15153089 ns 46 644.464kB/s
|
||||
// BM_MemmemStartup 5 ns 5 ns 150821500
|
||||
// BM_SearchStartup 5 ns 5 ns 150644203
|
||||
// BM_MemmatchStartup 7 ns 7 ns 97068802
|
||||
//
|
||||
// Conclusions:
|
||||
//
|
||||
// The following recommendations are based on the sample results above. However,
|
||||
// we have found that the performance of STL search can vary significantly
|
||||
// depending on compiler and standard library implementation. We recommend you
|
||||
// run the benchmarks for yourself on relevant platforms.
|
||||
//
|
||||
// If you need case-insensitive, STL search is slightly better than memmem for
|
||||
// all cases.
|
||||
//
|
||||
// Case-sensitive is more subtle:
|
||||
// Custom memmatch is _very_ fast at scanning, so if you have very few possible
|
||||
// matches in your haystack, that's the way to go. Performance drops
|
||||
// significantly with more matches.
|
||||
//
|
||||
// STL search is slightly faster than memmem in the medium and pathological
|
||||
// benchmarks. However, the performance of memmem is currently more dependable
|
||||
// across platforms and build configurations.
|
||||
|
||||
namespace { |
||||
|
||||
constexpr int kHaystackSize = 10000; |
||||
constexpr int64_t kHaystackSize64 = kHaystackSize; |
||||
const char* MakeHaystack() { |
||||
char* haystack = new char[kHaystackSize]; |
||||
for (int i = 0; i < kHaystackSize - 1; ++i) haystack[i] = 'a'; |
||||
haystack[kHaystackSize - 1] = 'b'; |
||||
return haystack; |
||||
} |
||||
const char* const kHaystack = MakeHaystack(); |
||||
|
||||
void BM_Memmem(benchmark::State& state) { |
||||
for (auto _ : state) { |
||||
benchmark::DoNotOptimize( |
||||
absl::strings_internal::memmem(kHaystack, kHaystackSize, "b", 1)); |
||||
} |
||||
state.SetBytesProcessed(kHaystackSize64 * state.iterations()); |
||||
} |
||||
BENCHMARK(BM_Memmem); |
||||
|
||||
void BM_MemmemMedium(benchmark::State& state) { |
||||
for (auto _ : state) { |
||||
benchmark::DoNotOptimize( |
||||
absl::strings_internal::memmem(kHaystack, kHaystackSize, "ab", 2)); |
||||
} |
||||
state.SetBytesProcessed(kHaystackSize64 * state.iterations()); |
||||
} |
||||
BENCHMARK(BM_MemmemMedium); |
||||
|
||||
void BM_MemmemPathological(benchmark::State& state) { |
||||
for (auto _ : state) { |
||||
benchmark::DoNotOptimize(absl::strings_internal::memmem( |
||||
kHaystack, kHaystackSize, kHaystack + kHaystackSize / 2, |
||||
kHaystackSize - kHaystackSize / 2)); |
||||
} |
||||
state.SetBytesProcessed(kHaystackSize64 * state.iterations()); |
||||
} |
||||
BENCHMARK(BM_MemmemPathological); |
||||
|
||||
void BM_Memcasemem(benchmark::State& state) { |
||||
for (auto _ : state) { |
||||
benchmark::DoNotOptimize( |
||||
absl::strings_internal::memcasemem(kHaystack, kHaystackSize, "b", 1)); |
||||
} |
||||
state.SetBytesProcessed(kHaystackSize64 * state.iterations()); |
||||
} |
||||
BENCHMARK(BM_Memcasemem); |
||||
|
||||
void BM_MemcasememMedium(benchmark::State& state) { |
||||
for (auto _ : state) { |
||||
benchmark::DoNotOptimize( |
||||
absl::strings_internal::memcasemem(kHaystack, kHaystackSize, "ab", 2)); |
||||
} |
||||
state.SetBytesProcessed(kHaystackSize64 * state.iterations()); |
||||
} |
||||
BENCHMARK(BM_MemcasememMedium); |
||||
|
||||
void BM_MemcasememPathological(benchmark::State& state) { |
||||
for (auto _ : state) { |
||||
benchmark::DoNotOptimize(absl::strings_internal::memcasemem( |
||||
kHaystack, kHaystackSize, kHaystack + kHaystackSize / 2, |
||||
kHaystackSize - kHaystackSize / 2)); |
||||
} |
||||
state.SetBytesProcessed(kHaystackSize64 * state.iterations()); |
||||
} |
||||
BENCHMARK(BM_MemcasememPathological); |
||||
|
||||
bool case_eq(const char a, const char b) { |
||||
return absl::ascii_tolower(a) == absl::ascii_tolower(b); |
||||
} |
||||
|
||||
void BM_Search(benchmark::State& state) { |
||||
for (auto _ : state) { |
||||
benchmark::DoNotOptimize(std::search(kHaystack, kHaystack + kHaystackSize, |
||||
kHaystack + kHaystackSize - 1, |
||||
kHaystack + kHaystackSize)); |
||||
} |
||||
state.SetBytesProcessed(kHaystackSize64 * state.iterations()); |
||||
} |
||||
BENCHMARK(BM_Search); |
||||
|
||||
void BM_SearchMedium(benchmark::State& state) { |
||||
for (auto _ : state) { |
||||
benchmark::DoNotOptimize(std::search(kHaystack, kHaystack + kHaystackSize, |
||||
kHaystack + kHaystackSize - 2, |
||||
kHaystack + kHaystackSize)); |
||||
} |
||||
state.SetBytesProcessed(kHaystackSize64 * state.iterations()); |
||||
} |
||||
BENCHMARK(BM_SearchMedium); |
||||
|
||||
void BM_SearchPathological(benchmark::State& state) { |
||||
for (auto _ : state) { |
||||
benchmark::DoNotOptimize(std::search(kHaystack, kHaystack + kHaystackSize, |
||||
kHaystack + kHaystackSize / 2, |
||||
kHaystack + kHaystackSize)); |
||||
} |
||||
state.SetBytesProcessed(kHaystackSize64 * state.iterations()); |
||||
} |
||||
BENCHMARK(BM_SearchPathological); |
||||
|
||||
void BM_Searchcase(benchmark::State& state) { |
||||
for (auto _ : state) { |
||||
benchmark::DoNotOptimize(std::search(kHaystack, kHaystack + kHaystackSize, |
||||
kHaystack + kHaystackSize - 1, |
||||
kHaystack + kHaystackSize, case_eq)); |
||||
} |
||||
state.SetBytesProcessed(kHaystackSize64 * state.iterations()); |
||||
} |
||||
BENCHMARK(BM_Searchcase); |
||||
|
||||
void BM_SearchcaseMedium(benchmark::State& state) { |
||||
for (auto _ : state) { |
||||
benchmark::DoNotOptimize(std::search(kHaystack, kHaystack + kHaystackSize, |
||||
kHaystack + kHaystackSize - 2, |
||||
kHaystack + kHaystackSize, case_eq)); |
||||
} |
||||
state.SetBytesProcessed(kHaystackSize64 * state.iterations()); |
||||
} |
||||
BENCHMARK(BM_SearchcaseMedium); |
||||
|
||||
void BM_SearchcasePathological(benchmark::State& state) { |
||||
for (auto _ : state) { |
||||
benchmark::DoNotOptimize(std::search(kHaystack, kHaystack + kHaystackSize, |
||||
kHaystack + kHaystackSize / 2, |
||||
kHaystack + kHaystackSize, case_eq)); |
||||
} |
||||
state.SetBytesProcessed(kHaystackSize64 * state.iterations()); |
||||
} |
||||
BENCHMARK(BM_SearchcasePathological); |
||||
|
||||
char* memcasechr(const char* s, int c, size_t slen) { |
||||
c = absl::ascii_tolower(c); |
||||
for (; slen; ++s, --slen) { |
||||
if (absl::ascii_tolower(*s) == c) return const_cast<char*>(s); |
||||
} |
||||
return nullptr; |
||||
} |
||||
|
||||
const char* memcasematch(const char* phaystack, size_t haylen, |
||||
const char* pneedle, size_t neelen) { |
||||
if (0 == neelen) { |
||||
return phaystack; // even if haylen is 0
|
||||
} |
||||
if (haylen < neelen) return nullptr; |
||||
|
||||
const char* match; |
||||
const char* hayend = phaystack + haylen - neelen + 1; |
||||
while ((match = static_cast<char*>( |
||||
memcasechr(phaystack, pneedle[0], hayend - phaystack)))) { |
||||
if (absl::strings_internal::memcasecmp(match, pneedle, neelen) == 0) |
||||
return match; |
||||
else |
||||
phaystack = match + 1; |
||||
} |
||||
return nullptr; |
||||
} |
||||
|
||||
void BM_Memmatch(benchmark::State& state) { |
||||
for (auto _ : state) { |
||||
benchmark::DoNotOptimize( |
||||
absl::strings_internal::memmatch(kHaystack, kHaystackSize, "b", 1)); |
||||
} |
||||
state.SetBytesProcessed(kHaystackSize64 * state.iterations()); |
||||
} |
||||
BENCHMARK(BM_Memmatch); |
||||
|
||||
void BM_MemmatchMedium(benchmark::State& state) { |
||||
for (auto _ : state) { |
||||
benchmark::DoNotOptimize( |
||||
absl::strings_internal::memmatch(kHaystack, kHaystackSize, "ab", 2)); |
||||
} |
||||
state.SetBytesProcessed(kHaystackSize64 * state.iterations()); |
||||
} |
||||
BENCHMARK(BM_MemmatchMedium); |
||||
|
||||
void BM_MemmatchPathological(benchmark::State& state) { |
||||
for (auto _ : state) { |
||||
benchmark::DoNotOptimize(absl::strings_internal::memmatch( |
||||
kHaystack, kHaystackSize, kHaystack + kHaystackSize / 2, |
||||
kHaystackSize - kHaystackSize / 2)); |
||||
} |
||||
state.SetBytesProcessed(kHaystackSize64 * state.iterations()); |
||||
} |
||||
BENCHMARK(BM_MemmatchPathological); |
||||
|
||||
void BM_Memcasematch(benchmark::State& state) { |
||||
for (auto _ : state) { |
||||
benchmark::DoNotOptimize(memcasematch(kHaystack, kHaystackSize, "b", 1)); |
||||
} |
||||
state.SetBytesProcessed(kHaystackSize64 * state.iterations()); |
||||
} |
||||
BENCHMARK(BM_Memcasematch); |
||||
|
||||
void BM_MemcasematchMedium(benchmark::State& state) { |
||||
for (auto _ : state) { |
||||
benchmark::DoNotOptimize(memcasematch(kHaystack, kHaystackSize, "ab", 2)); |
||||
} |
||||
state.SetBytesProcessed(kHaystackSize64 * state.iterations()); |
||||
} |
||||
BENCHMARK(BM_MemcasematchMedium); |
||||
|
||||
void BM_MemcasematchPathological(benchmark::State& state) { |
||||
for (auto _ : state) { |
||||
benchmark::DoNotOptimize(memcasematch(kHaystack, kHaystackSize, |
||||
kHaystack + kHaystackSize / 2, |
||||
kHaystackSize - kHaystackSize / 2)); |
||||
} |
||||
state.SetBytesProcessed(kHaystackSize64 * state.iterations()); |
||||
} |
||||
BENCHMARK(BM_MemcasematchPathological); |
||||
|
||||
void BM_MemmemStartup(benchmark::State& state) { |
||||
for (auto _ : state) { |
||||
benchmark::DoNotOptimize(absl::strings_internal::memmem( |
||||
kHaystack + kHaystackSize - 10, 10, kHaystack + kHaystackSize - 1, 1)); |
||||
} |
||||
} |
||||
BENCHMARK(BM_MemmemStartup); |
||||
|
||||
void BM_SearchStartup(benchmark::State& state) { |
||||
for (auto _ : state) { |
||||
benchmark::DoNotOptimize( |
||||
std::search(kHaystack + kHaystackSize - 10, kHaystack + kHaystackSize, |
||||
kHaystack + kHaystackSize - 1, kHaystack + kHaystackSize)); |
||||
} |
||||
} |
||||
BENCHMARK(BM_SearchStartup); |
||||
|
||||
void BM_MemmatchStartup(benchmark::State& state) { |
||||
for (auto _ : state) { |
||||
benchmark::DoNotOptimize(absl::strings_internal::memmatch( |
||||
kHaystack + kHaystackSize - 10, 10, kHaystack + kHaystackSize - 1, 1)); |
||||
} |
||||
} |
||||
BENCHMARK(BM_MemmatchStartup); |
||||
|
||||
} // namespace
|
@ -0,0 +1,72 @@ |
||||
// 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/time/clock.h" |
||||
|
||||
#if !defined(_WIN32) |
||||
#include <sys/time.h> |
||||
#endif // _WIN32
|
||||
#include <cstdio> |
||||
|
||||
#include "absl/base/internal/cycleclock.h" |
||||
#include "benchmark/benchmark.h" |
||||
|
||||
namespace { |
||||
|
||||
void BM_Clock_Now_AbslTime(benchmark::State& state) { |
||||
while (state.KeepRunning()) { |
||||
benchmark::DoNotOptimize(absl::Now()); |
||||
} |
||||
} |
||||
BENCHMARK(BM_Clock_Now_AbslTime); |
||||
|
||||
void BM_Clock_Now_GetCurrentTimeNanos(benchmark::State& state) { |
||||
while (state.KeepRunning()) { |
||||
benchmark::DoNotOptimize(absl::GetCurrentTimeNanos()); |
||||
} |
||||
} |
||||
BENCHMARK(BM_Clock_Now_GetCurrentTimeNanos); |
||||
|
||||
void BM_Clock_Now_AbslTime_ToUnixNanos(benchmark::State& state) { |
||||
while (state.KeepRunning()) { |
||||
benchmark::DoNotOptimize(absl::ToUnixNanos(absl::Now())); |
||||
} |
||||
} |
||||
BENCHMARK(BM_Clock_Now_AbslTime_ToUnixNanos); |
||||
|
||||
void BM_Clock_Now_CycleClock(benchmark::State& state) { |
||||
while (state.KeepRunning()) { |
||||
benchmark::DoNotOptimize(absl::base_internal::CycleClock::Now()); |
||||
} |
||||
} |
||||
BENCHMARK(BM_Clock_Now_CycleClock); |
||||
|
||||
#if !defined(_WIN32) |
||||
static void BM_Clock_Now_gettimeofday(benchmark::State& state) { |
||||
struct timeval tv; |
||||
while (state.KeepRunning()) { |
||||
benchmark::DoNotOptimize(gettimeofday(&tv, nullptr)); |
||||
} |
||||
} |
||||
BENCHMARK(BM_Clock_Now_gettimeofday); |
||||
|
||||
static void BM_Clock_Now_clock_gettime(benchmark::State& state) { |
||||
struct timespec ts; |
||||
while (state.KeepRunning()) { |
||||
benchmark::DoNotOptimize(clock_gettime(CLOCK_REALTIME, &ts)); |
||||
} |
||||
} |
||||
BENCHMARK(BM_Clock_Now_clock_gettime); |
||||
#endif // _WIN32
|
||||
|
||||
} // namespace
|
@ -0,0 +1,361 @@ |
||||
// 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 <cmath> |
||||
#include <cstddef> |
||||
#include <cstdint> |
||||
#include <ctime> |
||||
#include <string> |
||||
|
||||
#include "absl/time/time.h" |
||||
#include "benchmark/benchmark.h" |
||||
|
||||
namespace { |
||||
|
||||
//
|
||||
// Factory functions
|
||||
//
|
||||
|
||||
void BM_Duration_Factory_Nanoseconds(benchmark::State& state) { |
||||
while (state.KeepRunning()) { |
||||
benchmark::DoNotOptimize(absl::Nanoseconds(1)); |
||||
} |
||||
} |
||||
BENCHMARK(BM_Duration_Factory_Nanoseconds); |
||||
|
||||
void BM_Duration_Factory_Microseconds(benchmark::State& state) { |
||||
while (state.KeepRunning()) { |
||||
benchmark::DoNotOptimize(absl::Microseconds(1)); |
||||
} |
||||
} |
||||
BENCHMARK(BM_Duration_Factory_Microseconds); |
||||
|
||||
void BM_Duration_Factory_Milliseconds(benchmark::State& state) { |
||||
while (state.KeepRunning()) { |
||||
benchmark::DoNotOptimize(absl::Milliseconds(1)); |
||||
} |
||||
} |
||||
BENCHMARK(BM_Duration_Factory_Milliseconds); |
||||
|
||||
void BM_Duration_Factory_Seconds(benchmark::State& state) { |
||||
while (state.KeepRunning()) { |
||||
benchmark::DoNotOptimize(absl::Seconds(1)); |
||||
} |
||||
} |
||||
BENCHMARK(BM_Duration_Factory_Seconds); |
||||
|
||||
void BM_Duration_Factory_Minutes(benchmark::State& state) { |
||||
while (state.KeepRunning()) { |
||||
benchmark::DoNotOptimize(absl::Minutes(1)); |
||||
} |
||||
} |
||||
BENCHMARK(BM_Duration_Factory_Minutes); |
||||
|
||||
void BM_Duration_Factory_Hours(benchmark::State& state) { |
||||
while (state.KeepRunning()) { |
||||
benchmark::DoNotOptimize(absl::Hours(1)); |
||||
} |
||||
} |
||||
BENCHMARK(BM_Duration_Factory_Hours); |
||||
|
||||
//
|
||||
// Arithmetic
|
||||
//
|
||||
|
||||
void BM_Duration_Addition(benchmark::State& state) { |
||||
absl::Duration d = absl::Nanoseconds(1); |
||||
absl::Duration step = absl::Milliseconds(1); |
||||
while (state.KeepRunning()) { |
||||
benchmark::DoNotOptimize(d += step); |
||||
} |
||||
} |
||||
BENCHMARK(BM_Duration_Addition); |
||||
|
||||
void BM_Duration_Subtraction(benchmark::State& state) { |
||||
absl::Duration d = absl::Seconds(std::numeric_limits<int64_t>::max()); |
||||
absl::Duration step = absl::Milliseconds(1); |
||||
while (state.KeepRunning()) { |
||||
benchmark::DoNotOptimize(d -= step); |
||||
} |
||||
} |
||||
BENCHMARK(BM_Duration_Subtraction); |
||||
|
||||
void BM_Duration_Multiplication_Fixed(benchmark::State& state) { |
||||
absl::Duration d = absl::Milliseconds(1); |
||||
absl::Duration s; |
||||
int i = 0; |
||||
while (state.KeepRunning()) { |
||||
benchmark::DoNotOptimize(s += d * (i + 1)); |
||||
++i; |
||||
} |
||||
} |
||||
BENCHMARK(BM_Duration_Multiplication_Fixed); |
||||
|
||||
void BM_Duration_Multiplication_Double(benchmark::State& state) { |
||||
absl::Duration d = absl::Milliseconds(1); |
||||
absl::Duration s; |
||||
int i = 0; |
||||
while (state.KeepRunning()) { |
||||
benchmark::DoNotOptimize(s += d * (i + 1.0)); |
||||
++i; |
||||
} |
||||
} |
||||
BENCHMARK(BM_Duration_Multiplication_Double); |
||||
|
||||
void BM_Duration_Division_Fixed(benchmark::State& state) { |
||||
absl::Duration d = absl::Seconds(1); |
||||
int i = 0; |
||||
while (state.KeepRunning()) { |
||||
benchmark::DoNotOptimize(d /= i + 1); |
||||
++i; |
||||
} |
||||
} |
||||
BENCHMARK(BM_Duration_Division_Fixed); |
||||
|
||||
void BM_Duration_Division_Double(benchmark::State& state) { |
||||
absl::Duration d = absl::Seconds(1); |
||||
int i = 0; |
||||
while (state.KeepRunning()) { |
||||
benchmark::DoNotOptimize(d /= i + 1.0); |
||||
++i; |
||||
} |
||||
} |
||||
BENCHMARK(BM_Duration_Division_Double); |
||||
|
||||
void BM_Duration_FDivDuration_Nanoseconds(benchmark::State& state) { |
||||
double d = 1; |
||||
int i = 0; |
||||
while (state.KeepRunning()) { |
||||
benchmark::DoNotOptimize( |
||||
d += absl::FDivDuration(absl::Milliseconds(i), absl::Nanoseconds(1))); |
||||
++i; |
||||
} |
||||
} |
||||
BENCHMARK(BM_Duration_FDivDuration_Nanoseconds); |
||||
|
||||
void BM_Duration_IDivDuration_Nanoseconds(benchmark::State& state) { |
||||
int64_t a = 1; |
||||
absl::Duration ignore; |
||||
int i = 0; |
||||
while (state.KeepRunning()) { |
||||
benchmark::DoNotOptimize(a += |
||||
absl::IDivDuration(absl::Nanoseconds(i), |
||||
absl::Nanoseconds(1), &ignore)); |
||||
++i; |
||||
} |
||||
} |
||||
BENCHMARK(BM_Duration_IDivDuration_Nanoseconds); |
||||
|
||||
void BM_Duration_IDivDuration_Microseconds(benchmark::State& state) { |
||||
int64_t a = 1; |
||||
absl::Duration ignore; |
||||
int i = 0; |
||||
while (state.KeepRunning()) { |
||||
benchmark::DoNotOptimize(a += absl::IDivDuration(absl::Microseconds(i), |
||||
absl::Microseconds(1), |
||||
&ignore)); |
||||
++i; |
||||
} |
||||
} |
||||
BENCHMARK(BM_Duration_IDivDuration_Microseconds); |
||||
|
||||
void BM_Duration_IDivDuration_Milliseconds(benchmark::State& state) { |
||||
int64_t a = 1; |
||||
absl::Duration ignore; |
||||
int i = 0; |
||||
while (state.KeepRunning()) { |
||||
benchmark::DoNotOptimize(a += absl::IDivDuration(absl::Milliseconds(i), |
||||
absl::Milliseconds(1), |
||||
&ignore)); |
||||
++i; |
||||
} |
||||
} |
||||
BENCHMARK(BM_Duration_IDivDuration_Milliseconds); |
||||
|
||||
void BM_Duration_IDivDuration_Seconds(benchmark::State& state) { |
||||
int64_t a = 1; |
||||
absl::Duration ignore; |
||||
int i = 0; |
||||
while (state.KeepRunning()) { |
||||
benchmark::DoNotOptimize( |
||||
a += absl::IDivDuration(absl::Seconds(i), absl::Seconds(1), &ignore)); |
||||
++i; |
||||
} |
||||
} |
||||
BENCHMARK(BM_Duration_IDivDuration_Seconds); |
||||
|
||||
void BM_Duration_IDivDuration_Minutes(benchmark::State& state) { |
||||
int64_t a = 1; |
||||
absl::Duration ignore; |
||||
int i = 0; |
||||
while (state.KeepRunning()) { |
||||
benchmark::DoNotOptimize( |
||||
a += absl::IDivDuration(absl::Minutes(i), absl::Minutes(1), &ignore)); |
||||
++i; |
||||
} |
||||
} |
||||
BENCHMARK(BM_Duration_IDivDuration_Minutes); |
||||
|
||||
void BM_Duration_IDivDuration_Hours(benchmark::State& state) { |
||||
int64_t a = 1; |
||||
absl::Duration ignore; |
||||
int i = 0; |
||||
while (state.KeepRunning()) { |
||||
benchmark::DoNotOptimize( |
||||
a += absl::IDivDuration(absl::Hours(i), absl::Hours(1), &ignore)); |
||||
++i; |
||||
} |
||||
} |
||||
BENCHMARK(BM_Duration_IDivDuration_Hours); |
||||
|
||||
void BM_Duration_ToInt64Nanoseconds(benchmark::State& state) { |
||||
absl::Duration d = absl::Seconds(100000); |
||||
while (state.KeepRunning()) { |
||||
benchmark::DoNotOptimize(absl::ToInt64Nanoseconds(d)); |
||||
} |
||||
} |
||||
BENCHMARK(BM_Duration_ToInt64Nanoseconds); |
||||
|
||||
void BM_Duration_ToInt64Microseconds(benchmark::State& state) { |
||||
absl::Duration d = absl::Seconds(100000); |
||||
while (state.KeepRunning()) { |
||||
benchmark::DoNotOptimize(absl::ToInt64Microseconds(d)); |
||||
} |
||||
} |
||||
BENCHMARK(BM_Duration_ToInt64Microseconds); |
||||
|
||||
void BM_Duration_ToInt64Milliseconds(benchmark::State& state) { |
||||
absl::Duration d = absl::Seconds(100000); |
||||
while (state.KeepRunning()) { |
||||
benchmark::DoNotOptimize(absl::ToInt64Milliseconds(d)); |
||||
} |
||||
} |
||||
BENCHMARK(BM_Duration_ToInt64Milliseconds); |
||||
|
||||
void BM_Duration_ToInt64Seconds(benchmark::State& state) { |
||||
absl::Duration d = absl::Seconds(100000); |
||||
while (state.KeepRunning()) { |
||||
benchmark::DoNotOptimize(absl::ToInt64Seconds(d)); |
||||
} |
||||
} |
||||
BENCHMARK(BM_Duration_ToInt64Seconds); |
||||
|
||||
void BM_Duration_ToInt64Minutes(benchmark::State& state) { |
||||
absl::Duration d = absl::Seconds(100000); |
||||
while (state.KeepRunning()) { |
||||
benchmark::DoNotOptimize(absl::ToInt64Minutes(d)); |
||||
} |
||||
} |
||||
BENCHMARK(BM_Duration_ToInt64Minutes); |
||||
|
||||
void BM_Duration_ToInt64Hours(benchmark::State& state) { |
||||
absl::Duration d = absl::Seconds(100000); |
||||
while (state.KeepRunning()) { |
||||
benchmark::DoNotOptimize(absl::ToInt64Hours(d)); |
||||
} |
||||
} |
||||
BENCHMARK(BM_Duration_ToInt64Hours); |
||||
|
||||
//
|
||||
// To/FromTimespec
|
||||
//
|
||||
|
||||
void BM_Duration_ToTimespec_AbslTime(benchmark::State& state) { |
||||
absl::Duration d = absl::Seconds(1); |
||||
while (state.KeepRunning()) { |
||||
benchmark::DoNotOptimize(absl::ToTimespec(d)); |
||||
} |
||||
} |
||||
BENCHMARK(BM_Duration_ToTimespec_AbslTime); |
||||
|
||||
ABSL_ATTRIBUTE_NOINLINE timespec DoubleToTimespec(double seconds) { |
||||
timespec ts; |
||||
ts.tv_sec = seconds; |
||||
ts.tv_nsec = (seconds - ts.tv_sec) * (1000 * 1000 * 1000); |
||||
return ts; |
||||
} |
||||
|
||||
void BM_Duration_ToTimespec_Double(benchmark::State& state) { |
||||
while (state.KeepRunning()) { |
||||
benchmark::DoNotOptimize(DoubleToTimespec(1.0)); |
||||
} |
||||
} |
||||
BENCHMARK(BM_Duration_ToTimespec_Double); |
||||
|
||||
void BM_Duration_FromTimespec_AbslTime(benchmark::State& state) { |
||||
timespec ts; |
||||
ts.tv_sec = 0; |
||||
ts.tv_nsec = 0; |
||||
while (state.KeepRunning()) { |
||||
if (++ts.tv_nsec == 1000 * 1000 * 1000) { |
||||
++ts.tv_sec; |
||||
ts.tv_nsec = 0; |
||||
} |
||||
benchmark::DoNotOptimize(absl::DurationFromTimespec(ts)); |
||||
} |
||||
} |
||||
BENCHMARK(BM_Duration_FromTimespec_AbslTime); |
||||
|
||||
ABSL_ATTRIBUTE_NOINLINE double TimespecToDouble(timespec ts) { |
||||
return ts.tv_sec + (ts.tv_nsec / (1000 * 1000 * 1000)); |
||||
} |
||||
|
||||
void BM_Duration_FromTimespec_Double(benchmark::State& state) { |
||||
timespec ts; |
||||
ts.tv_sec = 0; |
||||
ts.tv_nsec = 0; |
||||
while (state.KeepRunning()) { |
||||
if (++ts.tv_nsec == 1000 * 1000 * 1000) { |
||||
++ts.tv_sec; |
||||
ts.tv_nsec = 0; |
||||
} |
||||
benchmark::DoNotOptimize(TimespecToDouble(ts)); |
||||
} |
||||
} |
||||
BENCHMARK(BM_Duration_FromTimespec_Double); |
||||
|
||||
//
|
||||
// String conversions
|
||||
//
|
||||
|
||||
const char* const kDurations[] = { |
||||
"0", // 0
|
||||
"123ns", // 1
|
||||
"1h2m3s", // 2
|
||||
"-2h3m4.005006007s", // 3
|
||||
"2562047788015215h30m7.99999999975s", // 4
|
||||
}; |
||||
const int kNumDurations = sizeof(kDurations) / sizeof(kDurations[0]); |
||||
|
||||
void BM_Duration_FormatDuration(benchmark::State& state) { |
||||
const std::string s = kDurations[state.range(0)]; |
||||
state.SetLabel(s); |
||||
absl::Duration d; |
||||
absl::ParseDuration(kDurations[state.range(0)], &d); |
||||
while (state.KeepRunning()) { |
||||
benchmark::DoNotOptimize(absl::FormatDuration(d)); |
||||
} |
||||
} |
||||
BENCHMARK(BM_Duration_FormatDuration)->DenseRange(0, kNumDurations - 1); |
||||
|
||||
void BM_Duration_ParseDuration(benchmark::State& state) { |
||||
const std::string s = kDurations[state.range(0)]; |
||||
state.SetLabel(s); |
||||
absl::Duration d; |
||||
while (state.KeepRunning()) { |
||||
benchmark::DoNotOptimize(absl::ParseDuration(s, &d)); |
||||
} |
||||
} |
||||
BENCHMARK(BM_Duration_ParseDuration)->DenseRange(0, kNumDurations - 1); |
||||
|
||||
} // namespace
|
@ -0,0 +1,63 @@ |
||||
// 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 <cstddef> |
||||
#include <string> |
||||
|
||||
#include "absl/time/internal/test_util.h" |
||||
#include "absl/time/time.h" |
||||
#include "benchmark/benchmark.h" |
||||
|
||||
namespace { |
||||
|
||||
namespace { |
||||
const char* const kFormats[] = { |
||||
absl::RFC1123_full, // 0
|
||||
absl::RFC1123_no_wday, // 1
|
||||
absl::RFC3339_full, // 2
|
||||
absl::RFC3339_sec, // 3
|
||||
"%Y-%m-%dT%H:%M:%S", // 4
|
||||
"%Y-%m-%d", // 5
|
||||
}; |
||||
const int kNumFormats = sizeof(kFormats) / sizeof(kFormats[0]); |
||||
} // namespace
|
||||
|
||||
void BM_Format_FormatTime(benchmark::State& state) { |
||||
const std::string fmt = kFormats[state.range(0)]; |
||||
state.SetLabel(fmt); |
||||
const absl::TimeZone lax = |
||||
absl::time_internal::LoadTimeZone("America/Los_Angeles"); |
||||
const absl::Time t = |
||||
absl::FromDateTime(1977, 6, 28, 9, 8, 7, lax) + absl::Nanoseconds(1); |
||||
while (state.KeepRunning()) { |
||||
benchmark::DoNotOptimize(absl::FormatTime(fmt, t, lax).length()); |
||||
} |
||||
} |
||||
BENCHMARK(BM_Format_FormatTime)->DenseRange(0, kNumFormats - 1); |
||||
|
||||
void BM_Format_ParseTime(benchmark::State& state) { |
||||
const std::string fmt = kFormats[state.range(0)]; |
||||
state.SetLabel(fmt); |
||||
const absl::TimeZone lax = |
||||
absl::time_internal::LoadTimeZone("America/Los_Angeles"); |
||||
absl::Time t = |
||||
absl::FromDateTime(1977, 6, 28, 9, 8, 7, lax) + absl::Nanoseconds(1); |
||||
const std::string when = absl::FormatTime(fmt, t, lax); |
||||
std::string err; |
||||
while (state.KeepRunning()) { |
||||
benchmark::DoNotOptimize(absl::ParseTime(fmt, when, lax, &t, &err)); |
||||
} |
||||
} |
||||
BENCHMARK(BM_Format_ParseTime)->DenseRange(0, kNumFormats - 1); |
||||
|
||||
} // namespace
|
@ -0,0 +1,316 @@ |
||||
// 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/time/time.h" |
||||
|
||||
#if !defined(_WIN32) |
||||
#include <sys/time.h> |
||||
#endif // _WIN32
|
||||
#include <algorithm> |
||||
#include <cmath> |
||||
#include <cstddef> |
||||
#include <cstring> |
||||
#include <ctime> |
||||
#include <memory> |
||||
#include <string> |
||||
|
||||
#include "absl/time/clock.h" |
||||
#include "absl/time/internal/test_util.h" |
||||
#include "benchmark/benchmark.h" |
||||
|
||||
namespace { |
||||
|
||||
//
|
||||
// Addition/Subtraction of a duration
|
||||
//
|
||||
|
||||
void BM_Time_Arithmetic(benchmark::State& state) { |
||||
const absl::Duration nano = absl::Nanoseconds(1); |
||||
const absl::Duration sec = absl::Seconds(1); |
||||
absl::Time t = absl::UnixEpoch(); |
||||
while (state.KeepRunning()) { |
||||
benchmark::DoNotOptimize(t += nano); |
||||
benchmark::DoNotOptimize(t -= sec); |
||||
} |
||||
} |
||||
BENCHMARK(BM_Time_Arithmetic); |
||||
|
||||
//
|
||||
// Time difference
|
||||
//
|
||||
|
||||
void BM_Time_Difference(benchmark::State& state) { |
||||
absl::Time start = absl::Now(); |
||||
absl::Time end = start + absl::Nanoseconds(1); |
||||
absl::Duration diff; |
||||
while (state.KeepRunning()) { |
||||
benchmark::DoNotOptimize(diff += end - start); |
||||
} |
||||
} |
||||
BENCHMARK(BM_Time_Difference); |
||||
|
||||
//
|
||||
// ToDateTime
|
||||
//
|
||||
// In each "ToDateTime" benchmark we switch between two instants
|
||||
// separated by at least one transition in order to defeat any
|
||||
// internal caching of previous results (e.g., see local_time_hint_).
|
||||
//
|
||||
// The "UTC" variants use UTC instead of the Google/local time zone.
|
||||
//
|
||||
|
||||
void BM_Time_ToDateTime_Absl(benchmark::State& state) { |
||||
const absl::TimeZone tz = |
||||
absl::time_internal::LoadTimeZone("America/Los_Angeles"); |
||||
absl::Time t = absl::FromUnixSeconds(1384569027); |
||||
absl::Time t2 = absl::FromUnixSeconds(1418962578); |
||||
while (state.KeepRunning()) { |
||||
std::swap(t, t2); |
||||
t += absl::Seconds(1); |
||||
benchmark::DoNotOptimize(t.In(tz)); |
||||
} |
||||
} |
||||
BENCHMARK(BM_Time_ToDateTime_Absl); |
||||
|
||||
void BM_Time_ToDateTime_Libc(benchmark::State& state) { |
||||
// No timezone support, so just use localtime.
|
||||
time_t t = 1384569027; |
||||
time_t t2 = 1418962578; |
||||
while (state.KeepRunning()) { |
||||
std::swap(t, t2); |
||||
t += 1; |
||||
struct tm tm; |
||||
#if !defined(_WIN32) |
||||
benchmark::DoNotOptimize(localtime_r(&t, &tm)); |
||||
#else // _WIN32
|
||||
benchmark::DoNotOptimize(localtime_s(&tm, &t)); |
||||
#endif // _WIN32
|
||||
} |
||||
} |
||||
BENCHMARK(BM_Time_ToDateTime_Libc); |
||||
|
||||
void BM_Time_ToDateTimeUTC_Absl(benchmark::State& state) { |
||||
const absl::TimeZone tz = absl::UTCTimeZone(); |
||||
absl::Time t = absl::FromUnixSeconds(1384569027); |
||||
while (state.KeepRunning()) { |
||||
t += absl::Seconds(1); |
||||
benchmark::DoNotOptimize(t.In(tz)); |
||||
} |
||||
} |
||||
BENCHMARK(BM_Time_ToDateTimeUTC_Absl); |
||||
|
||||
void BM_Time_ToDateTimeUTC_Libc(benchmark::State& state) { |
||||
time_t t = 1384569027; |
||||
while (state.KeepRunning()) { |
||||
t += 1; |
||||
struct tm tm; |
||||
#if !defined(_WIN32) |
||||
benchmark::DoNotOptimize(gmtime_r(&t, &tm)); |
||||
#else // _WIN32
|
||||
benchmark::DoNotOptimize(gmtime_s(&tm, &t)); |
||||
#endif // _WIN32
|
||||
} |
||||
} |
||||
BENCHMARK(BM_Time_ToDateTimeUTC_Libc); |
||||
|
||||
//
|
||||
// FromUnixMicros
|
||||
//
|
||||
|
||||
void BM_Time_FromUnixMicros(benchmark::State& state) { |
||||
int i = 0; |
||||
while (state.KeepRunning()) { |
||||
benchmark::DoNotOptimize(absl::FromUnixMicros(i)); |
||||
++i; |
||||
} |
||||
} |
||||
BENCHMARK(BM_Time_FromUnixMicros); |
||||
|
||||
void BM_Time_ToUnixNanos(benchmark::State& state) { |
||||
const absl::Time t = absl::UnixEpoch() + absl::Seconds(123); |
||||
while (state.KeepRunning()) { |
||||
benchmark::DoNotOptimize(ToUnixNanos(t)); |
||||
} |
||||
} |
||||
BENCHMARK(BM_Time_ToUnixNanos); |
||||
|
||||
void BM_Time_ToUnixMicros(benchmark::State& state) { |
||||
const absl::Time t = absl::UnixEpoch() + absl::Seconds(123); |
||||
while (state.KeepRunning()) { |
||||
benchmark::DoNotOptimize(ToUnixMicros(t)); |
||||
} |
||||
} |
||||
BENCHMARK(BM_Time_ToUnixMicros); |
||||
|
||||
void BM_Time_ToUnixMillis(benchmark::State& state) { |
||||
const absl::Time t = absl::UnixEpoch() + absl::Seconds(123); |
||||
while (state.KeepRunning()) { |
||||
benchmark::DoNotOptimize(ToUnixMillis(t)); |
||||
} |
||||
} |
||||
BENCHMARK(BM_Time_ToUnixMillis); |
||||
|
||||
void BM_Time_ToUnixSeconds(benchmark::State& state) { |
||||
const absl::Time t = absl::UnixEpoch() + absl::Seconds(123); |
||||
while (state.KeepRunning()) { |
||||
benchmark::DoNotOptimize(absl::ToUnixSeconds(t)); |
||||
} |
||||
} |
||||
BENCHMARK(BM_Time_ToUnixSeconds); |
||||
|
||||
//
|
||||
// FromDateTime
|
||||
//
|
||||
// In each "FromDateTime" benchmark we switch between two YMDhms
|
||||
// values separated by at least one transition in order to defeat any
|
||||
// internal caching of previous results (e.g., see time_local_hint_).
|
||||
//
|
||||
// The "UTC" variants use UTC instead of the Google/local time zone.
|
||||
// The "Day0" variants require normalization of the day of month.
|
||||
//
|
||||
|
||||
void BM_Time_FromDateTime_Absl(benchmark::State& state) { |
||||
const absl::TimeZone tz = |
||||
absl::time_internal::LoadTimeZone("America/Los_Angeles"); |
||||
int i = 0; |
||||
while (state.KeepRunning()) { |
||||
if ((i & 1) == 0) { |
||||
absl::FromDateTime(2014, 12, 18, 20, 16, 18, tz); |
||||
} else { |
||||
absl::FromDateTime(2013, 11, 15, 18, 30, 27, tz); |
||||
} |
||||
++i; |
||||
} |
||||
} |
||||
BENCHMARK(BM_Time_FromDateTime_Absl); |
||||
|
||||
void BM_Time_FromDateTime_Libc(benchmark::State& state) { |
||||
// No timezone support, so just use localtime.
|
||||
int i = 0; |
||||
while (state.KeepRunning()) { |
||||
struct tm tm; |
||||
if ((i & 1) == 0) { |
||||
tm.tm_year = 2014 - 1900; |
||||
tm.tm_mon = 12 - 1; |
||||
tm.tm_mday = 18; |
||||
tm.tm_hour = 20; |
||||
tm.tm_min = 16; |
||||
tm.tm_sec = 18; |
||||
} else { |
||||
tm.tm_year = 2013 - 1900; |
||||
tm.tm_mon = 11 - 1; |
||||
tm.tm_mday = 15; |
||||
tm.tm_hour = 18; |
||||
tm.tm_min = 30; |
||||
tm.tm_sec = 27; |
||||
} |
||||
tm.tm_isdst = -1; |
||||
mktime(&tm); |
||||
++i; |
||||
} |
||||
} |
||||
BENCHMARK(BM_Time_FromDateTime_Libc); |
||||
|
||||
void BM_Time_FromDateTimeUTC_Absl(benchmark::State& state) { |
||||
const absl::TimeZone tz = absl::UTCTimeZone(); |
||||
while (state.KeepRunning()) { |
||||
FromDateTime(2014, 12, 18, 20, 16, 18, tz); |
||||
} |
||||
} |
||||
BENCHMARK(BM_Time_FromDateTimeUTC_Absl); |
||||
|
||||
void BM_Time_FromDateTimeDay0_Absl(benchmark::State& state) { |
||||
const absl::TimeZone tz = |
||||
absl::time_internal::LoadTimeZone("America/Los_Angeles"); |
||||
int i = 0; |
||||
while (state.KeepRunning()) { |
||||
if ((i & 1) == 0) { |
||||
absl::FromDateTime(2014, 12, 0, 20, 16, 18, tz); |
||||
} else { |
||||
absl::FromDateTime(2013, 11, 0, 18, 30, 27, tz); |
||||
} |
||||
++i; |
||||
} |
||||
} |
||||
BENCHMARK(BM_Time_FromDateTimeDay0_Absl); |
||||
|
||||
void BM_Time_FromDateTimeDay0_Libc(benchmark::State& state) { |
||||
// No timezone support, so just use localtime.
|
||||
int i = 0; |
||||
while (state.KeepRunning()) { |
||||
struct tm tm; |
||||
if ((i & 1) == 0) { |
||||
tm.tm_year = 2014 - 1900; |
||||
tm.tm_mon = 12 - 1; |
||||
tm.tm_mday = 0; |
||||
tm.tm_hour = 20; |
||||
tm.tm_min = 16; |
||||
tm.tm_sec = 18; |
||||
} else { |
||||
tm.tm_year = 2013 - 1900; |
||||
tm.tm_mon = 11 - 1; |
||||
tm.tm_mday = 0; |
||||
tm.tm_hour = 18; |
||||
tm.tm_min = 30; |
||||
tm.tm_sec = 27; |
||||
} |
||||
tm.tm_isdst = -1; |
||||
mktime(&tm); |
||||
++i; |
||||
} |
||||
} |
||||
BENCHMARK(BM_Time_FromDateTimeDay0_Libc); |
||||
|
||||
//
|
||||
// To/FromTimespec
|
||||
//
|
||||
|
||||
void BM_Time_ToTimespec(benchmark::State& state) { |
||||
absl::Time now = absl::Now(); |
||||
while (state.KeepRunning()) { |
||||
benchmark::DoNotOptimize(absl::ToTimespec(now)); |
||||
} |
||||
} |
||||
BENCHMARK(BM_Time_ToTimespec); |
||||
|
||||
void BM_Time_FromTimespec(benchmark::State& state) { |
||||
timespec ts = absl::ToTimespec(absl::Now()); |
||||
while (state.KeepRunning()) { |
||||
if (++ts.tv_nsec == 1000 * 1000 * 1000) { |
||||
++ts.tv_sec; |
||||
ts.tv_nsec = 0; |
||||
} |
||||
benchmark::DoNotOptimize(absl::TimeFromTimespec(ts)); |
||||
} |
||||
} |
||||
BENCHMARK(BM_Time_FromTimespec); |
||||
|
||||
//
|
||||
// Comparison with InfiniteFuture/Past
|
||||
//
|
||||
|
||||
void BM_Time_InfiniteFuture(benchmark::State& state) { |
||||
while (state.KeepRunning()) { |
||||
benchmark::DoNotOptimize(absl::InfiniteFuture()); |
||||
} |
||||
} |
||||
BENCHMARK(BM_Time_InfiniteFuture); |
||||
|
||||
void BM_Time_InfinitePast(benchmark::State& state) { |
||||
while (state.KeepRunning()) { |
||||
benchmark::DoNotOptimize(absl::InfinitePast()); |
||||
} |
||||
} |
||||
BENCHMARK(BM_Time_InfinitePast); |
||||
|
||||
} // namespace
|
Loading…
Reference in new issue