Advertisement
Guest User

Untitled

a guest
May 27th, 2020
99
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.34 KB | None | 0 0
  1. #include <stdint.h>
  2. #include <stddef.h>
  3. #include <memory>
  4.  
  5. #include "testing/base/public/benchmark.h"
  6.  
  7. namespace {
  8.  
  9. template <int option>
  10. struct Vector {
  11. using allocator_type = std::allocator<int>;
  12. using __alloc_traits = std::allocator_traits<allocator_type>;
  13. using pointer = typename __alloc_traits::pointer;
  14. using size_type = size_t;
  15.  
  16. ~Vector() { __alloc_traits::deallocate(alloc_, begin_, end_cap_ - begin_); }
  17.  
  18. void reserve(size_type n) {
  19. if (n > capacity()) {
  20. __grow(n);
  21. }
  22. }
  23.  
  24. void clear() { end_ = begin_; }
  25.  
  26. void push_back(int value) {
  27. if (option == 1) {
  28. pointer end = end_;
  29. if (end == end_cap_) {
  30. size_type sz = end_ - begin_;
  31. size_type n = sz ? sz * 2 : 2;
  32. __push_back_slow_path(n, value);
  33. } else {
  34. *end = value;
  35. end_ = end + 1;
  36. }
  37. } else if (option == 2) {
  38. pointer end = end_;
  39. if (end == end_cap_) {
  40. size_type sz = end_ - begin_;
  41. size_type n = sz ? sz * 2 : 2;
  42. __push_back_slow_path(n, value);
  43. end = end_ - 1;
  44. } else {
  45. *end = value;
  46. }
  47. end_ = end + 1;
  48. } else if (option == 3) {
  49. pointer end = end_;
  50. if (end == end_cap_) {
  51. size_type sz = end_ - begin_;
  52. size_type n = sz ? sz * 2 : 2;
  53. begin_ = __push_back_slow_path(begin_, sz, n, value);
  54. end_ = end = begin_ + sz;
  55. end_cap_ = begin_ + n;
  56. } else {
  57. *end = value;
  58. end_ = end + 1;
  59. }
  60. }
  61. }
  62.  
  63. int* data() { return begin_; }
  64. size_type size() const { return end_ - begin_; }
  65. size_type capacity() const { return end_cap_ - begin_; }
  66.  
  67. private:
  68. struct buffer {
  69. pointer begin;
  70. pointer first;
  71. pointer end;
  72. pointer end_cap;
  73.  
  74. buffer(size_t sz, size_type n) {
  75. allocator_type alloc;
  76. begin = __alloc_traits::allocate(alloc, n);
  77. first = end = begin + sz;
  78. end_cap = begin + n;
  79. }
  80.  
  81. ~buffer() {
  82. allocator_type alloc;
  83. __alloc_traits::deallocate(alloc, begin, end_cap - begin);
  84. }
  85.  
  86. void construct_backwards(int i) { *(--first) = i; }
  87.  
  88. void construct_backwards(pointer begin, pointer end) {
  89. while (end != begin) {
  90. *(--first) = *(--end);
  91. }
  92. }
  93. };
  94.  
  95. void __swap_in_buffer(buffer& b);
  96.  
  97. void __grow(size_type n);
  98. void __push_back_slow_path(size_type n, int i);
  99. static pointer __push_back_slow_path(pointer begin,
  100. size_type sz, size_type n, int i);
  101.  
  102. [[no_unique_address]] allocator_type alloc_;
  103. pointer begin_ = nullptr;
  104. pointer end_ = nullptr;
  105. pointer end_cap_ = nullptr;
  106. };
  107.  
  108. template <int option>
  109. void Vector<option>::__swap_in_buffer(buffer& b) {
  110. b.first = begin_;
  111. begin_ = b.begin;
  112. b.begin = b.first;
  113. std::swap(b.end, end_);
  114. std::swap(b.end_cap, end_cap_);
  115. }
  116.  
  117. template <int option>
  118. void Vector<option>::__grow(size_type n) {
  119. size_type sz = end_ - begin_;
  120. buffer b(sz, n);
  121. b.construct_backwards(begin_, begin_ + sz);
  122. __swap_in_buffer(b);
  123. }
  124.  
  125. template <int option>
  126. #if !defined(INLINE_SLOW_PATH)
  127. __attribute__((noinline))
  128. #endif
  129. void Vector<option>::__push_back_slow_path(size_type n, int value) {
  130. size_t sz = end_ - begin_;
  131. buffer b(sz + 1, n);
  132. b.construct_backwards(value);
  133. b.construct_backwards(begin_, end_);
  134. __swap_in_buffer(b);
  135. }
  136.  
  137. template <int option>
  138. #if !defined(INLINE_SLOW_PATH)
  139. __attribute__((noinline))
  140. #endif
  141. typename Vector<option>::pointer
  142. Vector<option>::__push_back_slow_path(pointer begin, size_t sz, size_type n,
  143. int value) {
  144. buffer b(sz + 1, n);
  145. b.construct_backwards(value);
  146. b.construct_backwards(begin, begin + sz);
  147.  
  148. b.end = begin + sz;
  149. b.end_cap = begin + n;
  150.  
  151. b.first = begin;
  152. begin = b.begin;
  153. b.begin = b.first;
  154.  
  155. return begin;
  156. }
  157.  
  158. template <typename Vector>
  159. void BM_Pushback(benchmark::State& state) {
  160. int count = state.range(0);
  161. Vector vec;
  162. vec.reserve(count);
  163. while (state.KeepRunningBatch(count)) {
  164. vec.clear();
  165. #pragma nounroll
  166. for (int i = 0; i < count; ++i) {
  167. vec.push_back(i);
  168. }
  169. testing::DoNotOptimize(vec.data());
  170. }
  171. }
  172.  
  173. BENCHMARK(BM_Pushback<Vector<1>>)->Arg(4000);
  174. BENCHMARK(BM_Pushback<Vector<2>>)->Arg(4000);
  175. BENCHMARK(BM_Pushback<Vector<3>>)->Arg(4000);
  176.  
  177. } // namespace
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement