Skip to content

Commit

Permalink
Add benchmark tests
Browse files Browse the repository at this point in the history
  • Loading branch information
winner245 committed Nov 7, 2024
1 parent ae7a50e commit 9397cb4
Show file tree
Hide file tree
Showing 4 changed files with 109 additions and 2 deletions.
4 changes: 2 additions & 2 deletions libcxx/include/__vector/vector.h
Original file line number Diff line number Diff line change
Expand Up @@ -1285,8 +1285,8 @@ vector<_Tp, _Allocator>::__insert_with_sentinel(const_iterator __position, _Inpu
std::__uninitialized_allocator_relocate(
__a, std::__to_address(__v.__begin_), std::__to_address(__v.__end_), std::__to_address(__merged.__end_));
__merged.__end_ += __v.size();
__v.__end_ = __v.__begin_;
__p = __swap_out_circular_buffer(__merged, __p);
__v.__end_ = __v.__begin_;
__p = __swap_out_circular_buffer(__merged, __p);
}
return __make_iter(__p);
}
Expand Down
84 changes: 84 additions & 0 deletions libcxx/test/benchmarks/ContainerBenchmarks.h
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,90 @@ void BM_InsertValueRehash(benchmark::State& st, Container c, GenInputs gen) {
}
}

// Wrap any Iterator into an input iterator
template <typename Iterator>
class InputIterator {
using iter_traits = std::iterator_traits<Iterator>;

public:
using iterator_category = std::input_iterator_tag;
using value_type = typename iter_traits::value_type;
using difference_type = typename iter_traits::difference_type;
using pointer = typename iter_traits::pointer;
using reference = typename iter_traits::reference;

InputIterator(Iterator it) : current_(it) {}

reference operator*() { return *current_; }
InputIterator& operator++() {
++current_;
return *this;
}
InputIterator operator++(int) {
InputIterator tmp = *this;
++(*this);
return tmp;
}

friend bool operator==(const InputIterator& lhs, const InputIterator& rhs) { return lhs.current_ == rhs.current_; }
friend bool operator!=(const InputIterator& lhs, const InputIterator& rhs) { return !(lhs == rhs); }

private:
Iterator current_;
};

template <typename Iterator>
InputIterator<Iterator> make_input_iterator(Iterator it) {
return InputIterator<Iterator>(it);
}

// Test case: vector is empty
template <class Container, class GenInputs>
void BM_InsertIterInputIterIterEmpty(benchmark::State& st, Container _, GenInputs gen) {
auto in = gen(st.range(0));
benchmark::DoNotOptimize(&in);
for (auto _ : st) {
Container c;
benchmark::DoNotOptimize(&c);
benchmark::DoNotOptimize(c.insert(c.begin(), make_input_iterator(in.begin()), make_input_iterator(in.end())));
benchmark::ClobberMemory();
}
}

// Test case: vector is half full
template <class Container, class GenInputs>
void BM_InsertIterInputIterIterHalfFull(benchmark::State& st, Container c, GenInputs gen) {
for (auto _ : st) {
st.PauseTiming();
c = gen(st.range(0));
c.reserve(c.size() * 2);
auto in = gen(c.size() + 10);
benchmark::DoNotOptimize(&c);
benchmark::DoNotOptimize(&in);
st.ResumeTiming();

benchmark::DoNotOptimize(c.insert(c.begin(), make_input_iterator(in.begin()), make_input_iterator(in.end())));
benchmark::ClobberMemory();
}
}

// Test case: vector is almost full
template <class Container, class GenInputs>
void BM_InsertIterInputIterIterFull(benchmark::State& st, Container c, GenInputs gen) {
for (auto _ : st) {
st.PauseTiming();
c = gen(st.range(0));
c.reserve(c.size() + 5);
auto in = gen(10);
benchmark::DoNotOptimize(&c);
benchmark::DoNotOptimize(&in);
st.ResumeTiming();

benchmark::DoNotOptimize(c.insert(c.begin(), make_input_iterator(in.begin()), make_input_iterator(in.end())));
benchmark::ClobberMemory();
}
}

template <class Container, class GenInputs>
void BM_InsertDuplicate(benchmark::State& st, Container c, GenInputs gen) {
auto in = gen(st.range(0));
Expand Down
7 changes: 7 additions & 0 deletions libcxx/test/benchmarks/GenerateInput.h
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,13 @@ inline std::vector<std::string> getRandomStringInputs(size_t N) {
return inputs;
}

inline std::vector<std::string> getShortRandomStringInputs(size_t N) {
std::vector<std::string> inputs;
for (size_t i = 0; i < N; ++i)
inputs.push_back(getRandomString(10)); // SSO
return inputs;
}

inline std::vector<std::string> getPrefixedRandomStringInputs(size_t N) {
std::vector<std::string> inputs;
constexpr int kSuffixLength = 32;
Expand Down
16 changes: 16 additions & 0 deletions libcxx/test/benchmarks/vector_operations.bench.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,4 +67,20 @@ BENCHMARK(bm_grow<std::string>);
BENCHMARK(bm_grow<std::unique_ptr<int>>);
BENCHMARK(bm_grow<std::deque<int>>);

BENCHMARK_CAPTURE(BM_InsertIterInputIterIterEmpty, vector_int, std::vector<int>{}, getRandomIntegerInputs<int>)
->Arg(TestNumInputs);
BENCHMARK_CAPTURE(BM_InsertIterInputIterIterHalfFull, vector_int, std::vector<int>{}, getRandomIntegerInputs<int>)
->Arg(TestNumInputs);
BENCHMARK_CAPTURE(BM_InsertIterInputIterIterFull, vector_int, std::vector<int>{}, getRandomIntegerInputs<int>)
->Arg(TestNumInputs);

BENCHMARK_CAPTURE(
BM_InsertIterInputIterIterEmpty, vector_string, std::vector<std::string>{}, getShortRandomStringInputs)
->Arg(TestNumInputs);
BENCHMARK_CAPTURE(
BM_InsertIterInputIterIterHalfFull, vector_string, std::vector<std::string>{}, getShortRandomStringInputs)
->Arg(TestNumInputs);
BENCHMARK_CAPTURE(BM_InsertIterInputIterIterFull, vector_string, std::vector<std::string>{}, getShortRandomStringInputs)
->Arg(TestNumInputs);

BENCHMARK_MAIN();

0 comments on commit 9397cb4

Please sign in to comment.