layout_benchmark.cc 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. // Copyright 2018 The Abseil Authors.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // https://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. //
  15. // Every benchmark should have the same performance as the corresponding
  16. // headroom benchmark.
  17. #include "absl/base/internal/raw_logging.h"
  18. #include "absl/container/internal/layout.h"
  19. #include "benchmark/benchmark.h"
  20. namespace absl {
  21. ABSL_NAMESPACE_BEGIN
  22. namespace container_internal {
  23. namespace {
  24. using ::benchmark::DoNotOptimize;
  25. using Int128 = int64_t[2];
  26. // This benchmark provides the upper bound on performance for BM_OffsetConstant.
  27. template <size_t Offset, class... Ts>
  28. void BM_OffsetConstantHeadroom(benchmark::State& state) {
  29. for (auto _ : state) {
  30. DoNotOptimize(Offset);
  31. }
  32. }
  33. template <size_t Offset, class... Ts>
  34. void BM_OffsetConstant(benchmark::State& state) {
  35. using L = Layout<Ts...>;
  36. ABSL_RAW_CHECK(L::Partial(3, 5, 7).template Offset<3>() == Offset,
  37. "Invalid offset");
  38. for (auto _ : state) {
  39. DoNotOptimize(L::Partial(3, 5, 7).template Offset<3>());
  40. }
  41. }
  42. template <class... Ts>
  43. size_t VariableOffset(size_t n, size_t m, size_t k);
  44. template <>
  45. size_t VariableOffset<int8_t, int16_t, int32_t, Int128>(size_t n, size_t m,
  46. size_t k) {
  47. auto Align = [](size_t n, size_t m) { return (n + m - 1) & ~(m - 1); };
  48. return Align(Align(Align(n * 1, 2) + m * 2, 4) + k * 4, 8);
  49. }
  50. template <>
  51. size_t VariableOffset<Int128, int32_t, int16_t, int8_t>(size_t n, size_t m,
  52. size_t k) {
  53. // No alignment is necessary.
  54. return n * 16 + m * 4 + k * 2;
  55. }
  56. // This benchmark provides the upper bound on performance for BM_OffsetVariable.
  57. template <size_t Offset, class... Ts>
  58. void BM_OffsetVariableHeadroom(benchmark::State& state) {
  59. size_t n = 3;
  60. size_t m = 5;
  61. size_t k = 7;
  62. ABSL_RAW_CHECK(VariableOffset<Ts...>(n, m, k) == Offset, "Invalid offset");
  63. for (auto _ : state) {
  64. DoNotOptimize(n);
  65. DoNotOptimize(m);
  66. DoNotOptimize(k);
  67. DoNotOptimize(VariableOffset<Ts...>(n, m, k));
  68. }
  69. }
  70. template <size_t Offset, class... Ts>
  71. void BM_OffsetVariable(benchmark::State& state) {
  72. using L = Layout<Ts...>;
  73. size_t n = 3;
  74. size_t m = 5;
  75. size_t k = 7;
  76. ABSL_RAW_CHECK(L::Partial(n, m, k).template Offset<3>() == Offset,
  77. "Inavlid offset");
  78. for (auto _ : state) {
  79. DoNotOptimize(n);
  80. DoNotOptimize(m);
  81. DoNotOptimize(k);
  82. DoNotOptimize(L::Partial(n, m, k).template Offset<3>());
  83. }
  84. }
  85. // Run all benchmarks in two modes:
  86. //
  87. // Layout with padding: int8_t[3], int16_t[5], int32_t[7], Int128[?].
  88. // Layout without padding: Int128[3], int32_t[5], int16_t[7], int8_t[?].
  89. #define OFFSET_BENCHMARK(NAME, OFFSET, T1, T2, T3, T4) \
  90. auto& NAME##_##OFFSET##_##T1##_##T2##_##T3##_##T4 = \
  91. NAME<OFFSET, T1, T2, T3, T4>; \
  92. BENCHMARK(NAME##_##OFFSET##_##T1##_##T2##_##T3##_##T4)
  93. OFFSET_BENCHMARK(BM_OffsetConstantHeadroom, 48, int8_t, int16_t, int32_t,
  94. Int128);
  95. OFFSET_BENCHMARK(BM_OffsetConstant, 48, int8_t, int16_t, int32_t, Int128);
  96. OFFSET_BENCHMARK(BM_OffsetConstantHeadroom, 82, Int128, int32_t, int16_t,
  97. int8_t);
  98. OFFSET_BENCHMARK(BM_OffsetConstant, 82, Int128, int32_t, int16_t, int8_t);
  99. OFFSET_BENCHMARK(BM_OffsetVariableHeadroom, 48, int8_t, int16_t, int32_t,
  100. Int128);
  101. OFFSET_BENCHMARK(BM_OffsetVariable, 48, int8_t, int16_t, int32_t, Int128);
  102. OFFSET_BENCHMARK(BM_OffsetVariableHeadroom, 82, Int128, int32_t, int16_t,
  103. int8_t);
  104. OFFSET_BENCHMARK(BM_OffsetVariable, 82, Int128, int32_t, int16_t, int8_t);
  105. } // namespace
  106. } // namespace container_internal
  107. ABSL_NAMESPACE_END
  108. } // namespace absl