Skip to content

Commit

Permalink
insert/emplace implementation improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
KRM7 committed Mar 16, 2024
1 parent 87a1bcd commit 3e07056
Show file tree
Hide file tree
Showing 4 changed files with 227 additions and 154 deletions.
115 changes: 53 additions & 62 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,95 +1,86 @@
### `small_vector<T>`

```shell
g++ 12.3.0 -std=c++20 -O3 -flto -DNDEBUG
```

```shell
small_vector_benchmark --benchmark_enable_random_interleaving=true --benchmark_repetitions=10
small_vector_benchmark --benchmark_min_warmup_time=2
```

```text
-----------------------------------------------------------------------------------------------------------------
Benchmark Time CPU Iterations
-----------------------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------------
Benchmark Time CPU Iterations
----------------------------------------------------------------------------------------------------------
// construct_from_size
benchmark_construct_from_size<std::vector<int>>/size:4_median 11.1 ns 11.1 ns 10
benchmark_construct_from_size<small_vector<int>>/size:4_median 1.84 ns 1.84 ns 10
benchmark_construct_from_size<std::vector<int>>/size:100_median 11.5 ns 11.5 ns 10
benchmark_construct_from_size<small_vector<int>>/size:100_median 11.5 ns 11.5 ns 10
// construct_size_value
benchmark_construct_from_size_value<std::vector<int>>/size:4_median 10.2 ns 10.2 ns 10
benchmark_construct_from_size_value<small_vector<int>>/size:4_median 1.61 ns 1.61 ns 10
benchmark_construct_from_size<std::vector<int>>/size:4 11.1 ns 11.1 ns 63128125
benchmark_construct_from_size<std::vector<int>>/size:100 11.5 ns 11.5 ns 60983419
benchmark_construct_from_size<small_vector<int>>/size:4 1.85 ns 1.85 ns 379357325
benchmark_construct_from_size<small_vector<int>>/size:100 11.7 ns 11.7 ns 59806415
benchmark_construct_from_size_value<std::vector<int>>/size:100_median 16.4 ns 16.4 ns 10
benchmark_construct_from_size_value<small_vector<int>>/size:100_median 17.5 ns 17.5 ns 10
// construct_from_size_value
benchmark_construct_from_size_value<std::vector<int>>/size:4 10.6 ns 10.6 ns 66230178
benchmark_construct_from_size_value<std::vector<int>>/size:100 17.2 ns 17.2 ns 41003124
benchmark_construct_from_size_value<small_vector<int>>/size:4 1.84 ns 1.84 ns 379785020
benchmark_construct_from_size_value<small_vector<int>>/size:100 17.7 ns 17.7 ns 39628556
// construct_from_range
benchmark_construct_from_range<std::vector<int>>/size:4_median 11.4 ns 11.4 ns 10
benchmark_construct_from_range<small_vector<int>>/size:4_median 2.31 ns 2.31 ns 10
benchmark_construct_from_range<std::vector<int>>/size:100_median 12.7 ns 12.7 ns 10
benchmark_construct_from_range<small_vector<int>>/size:100_median 13.4 ns 13.4 ns 10
benchmark_construct_from_range<std::vector<int>>/size:4 11.4 ns 11.4 ns 61351468
benchmark_construct_from_range<std::vector<int>>/size:100 12.6 ns 12.6 ns 55381324
benchmark_construct_from_range<small_vector<int>>/size:4 2.31 ns 2.31 ns 303092496
benchmark_construct_from_range<small_vector<int>>/size:100 13.2 ns 13.2 ns 53144806
// assign_reserved
benchmark_assign_reserved<std::vector<int>>/size:4_median 2.53 ns 2.53 ns 10
benchmark_assign_reserved<small_vector<int>>/size:4_median 2.32 ns 2.32 ns 10
benchmark_assign_reserved<std::vector<int>>/size:100_median 4.38 ns 4.38 ns 10
benchmark_assign_reserved<small_vector<int>>/size:100_median 4.61 ns 4.61 ns 10
benchmark_assign_reserved<std::vector<int>>/size:4 2.30 ns 2.30 ns 300733274
benchmark_assign_reserved<std::vector<int>>/size:100 4.93 ns 4.93 ns 141963555
benchmark_assign_reserved<small_vector<int>>/size:4 2.30 ns 2.30 ns 303034501
benchmark_assign_reserved<small_vector<int>>/size:100 5.28 ns 5.28 ns 132612176
// swap
benchmark_swap<std::vector<int>>/size:4_median 1.34 ns 1.34 ns 10
benchmark_swap<small_vector<int>>/size:4_median 3.92 ns 3.92 ns 10
benchmark_swap<std::vector<int>>/size:100_median 1.34 ns 1.34 ns 10
benchmark_swap<small_vector<int>>/size:100_median 1.84 ns 1.84 ns 10
benchmark_swap<std::vector<int>>/size:4 1.34 ns 1.34 ns 518765605
benchmark_swap<std::vector<int>>/size:100 1.33 ns 1.33 ns 522469939
benchmark_swap<small_vector<int>>/size:4 4.15 ns 4.15 ns 168877555
benchmark_swap<small_vector<int>>/size:100 1.84 ns 1.84 ns 380621991
// resize
benchmark_resize<std::vector<int>>/size:4_median 1.61 ns 1.61 ns 10
benchmark_resize<small_vector<int>>/size:4_median 2.77 ns 2.77 ns 10
benchmark_resize<std::vector<int>>/size:100_median 1.61 ns 1.61 ns 10
benchmark_resize<small_vector<int>>/size:100_median 2.77 ns 2.77 ns 10
benchmark_resize<std::vector<int>>/size:4 2.54 ns 2.54 ns 275839458
benchmark_resize<std::vector<int>>/size:100 3.67 ns 3.67 ns 197377975
benchmark_resize<small_vector<int>>/size:4 1.87 ns 1.87 ns 376250226
benchmark_resize<small_vector<int>>/size:100 3.28 ns 3.28 ns 215127588
// push_back_reserved
benchmark_push_back_reserved<std::vector<int>>/size:4_median 0.923 ns 0.923 ns 10
benchmark_push_back_reserved<small_vector<int>>/size:4_median 0.952 ns 0.952 ns 10
benchmark_push_back_reserved<std::vector<int>>/size:100_median 0.923 ns 0.923 ns 10
benchmark_push_back_reserved<small_vector<int>>/size:100_median 0.952 ns 0.952 ns 10
benchmark_push_back_reserved<std::vector<int>>/size:4 0.613 ns 0.613 ns 1000000000
benchmark_push_back_reserved<std::vector<int>>/size:100 0.618 ns 0.618 ns 1000000000
benchmark_push_back_reserved<small_vector<int>>/size:4 0.562 ns 0.562 ns 1000000000
benchmark_push_back_reserved<small_vector<int>>/size:100 0.617 ns 0.618 ns 1000000000
// push_back_reallocate
benchmark_push_back_reallocate<std::vector<int>>/size:100_median 143 ns 143 ns 10
benchmark_push_back_reallocate<small_vector<int>>/size:100_median 126 ns 126 ns 10
benchmark_push_back_reallocate<std::vector<int>>/size:100 144 ns 144 ns 4641722
benchmark_push_back_reallocate<small_vector<int>>/size:100 148 ns 148 ns 4781649
// insert_one_reserved
benchmark_insert_one_reserved<std::vector<int>>/size:4_median 4.63 ns 4.63 ns 10
benchmark_insert_one_reserved<small_vector<int>>/size:4_median 4.61 ns 4.61 ns 10
benchmark_insert_one_reserved<std::vector<int>>/size:100_median 8.20 ns 8.20 ns 10
benchmark_insert_one_reserved<small_vector<int>>/size:100_median 7.74 ns 7.74 ns 10
benchmark_insert_one_reserved<std::vector<int>>/size:4 4.66 ns 4.66 ns 150091813
benchmark_insert_one_reserved<std::vector<int>>/size:100 8.01 ns 8.01 ns 85894208
benchmark_insert_one_reserved<small_vector<int>>/size:4 4.65 ns 4.65 ns 149969588
benchmark_insert_one_reserved<small_vector<int>>/size:100 8.17 ns 8.17 ns 86572377
// insert_one_reallocate
benchmark_insert_one_reallocate<std::vector<int>>/size:100_median 737 ns 737 ns 10
benchmark_insert_one_reallocate<small_vector<int>>/size:100_median 747 ns 747 ns 10
benchmark_insert_one_reallocate<std::vector<int>>/size:100 728 ns 728 ns 965758
benchmark_insert_one_reallocate<small_vector<int>>/size:100 752 ns 752 ns 939354
// insert_range_reserved
benchmark_insert_range_reserved<std::vector<int>>/size:4_median 5.30 ns 5.30 ns 10
benchmark_insert_range_reserved<small_vector<int>>/size:4_median 6.46 ns 6.46 ns 10
benchmark_insert_range_reserved<std::vector<int>>/size:100_median 8.56 ns 8.56 ns 10
benchmark_insert_range_reserved<small_vector<int>>/size:100_median 6.45 ns 6.45 ns 10
benchmark_insert_range_reserved<std::vector<int>>/size:4 6.12 ns 6.12 ns 116646059
benchmark_insert_range_reserved<std::vector<int>>/size:100 8.62 ns 8.62 ns 82369900
benchmark_insert_range_reserved<small_vector<int>>/size:4 6.26 ns 6.26 ns 112617323
benchmark_insert_range_reserved<small_vector<int>>/size:100 6.29 ns 6.29 ns 112590153
// insert_range_reallocate
benchmark_insert_range_reallocate<std::vector<int>>/size:100_median 234 ns 233 ns 10
benchmark_insert_range_reallocate<small_vector<int>>/size:100_median 251 ns 251 ns 10
benchmark_insert_range_reallocate<std::vector<int>>/size:100 255 ns 255 ns 2707667
benchmark_insert_range_reallocate<small_vector<int>>/size:100 229 ns 229 ns 3066817
// erase_front
benchmark_erase<std::vector<int>>/size:4_median 4.84 ns 4.84 ns 10
benchmark_erase<small_vector<int>>/size:4_median 5.54 ns 5.54 ns 10
benchmark_erase<std::vector<int>>/size:100_median 8.43 ns 8.43 ns 10
benchmark_erase<small_vector<int>>/size:100_median 8.36 ns 8.36 ns 10
benchmark_erase<std::vector<int>>/size:4 4.88 ns 4.88 ns 143511026
benchmark_erase<std::vector<int>>/size:100 8.51 ns 8.51 ns 82108933
benchmark_erase<small_vector<int>>/size:4 4.62 ns 4.62 ns 150378007
benchmark_erase<small_vector<int>>/size:100 8.53 ns 8.53 ns 82985683
```
29 changes: 22 additions & 7 deletions benchmark/small_vector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,11 @@ inline constexpr size_t LARGE_SIZE = 100;
template<typename V>
void benchmark_construct_from_size(benchmark::State& state)
{
const size_t size = state.range(0);
size_t size = state.range(0);

for (auto _ : state)
{
benchmark::DoNotOptimize(size);
V vec(size);
benchmark::DoNotOptimize(vec);
benchmark::ClobberMemory();
Expand All @@ -29,11 +30,14 @@ BENCHMARK(benchmark_construct_from_size<small_vector<int>>)->ArgName("size")->Ar
template<typename V>
void benchmark_construct_from_size_value(benchmark::State& state)
{
const size_t size = state.range(0);
size_t size = state.range(0);
int value = 2;

for (auto _ : state)
{
V vec(size, 2);
benchmark::DoNotOptimize(size);
benchmark::DoNotOptimize(value);
V vec(size, value);
benchmark::DoNotOptimize(vec);
benchmark::ClobberMemory();
}
Expand All @@ -47,10 +51,11 @@ BENCHMARK(benchmark_construct_from_size_value<small_vector<int>>)->ArgName("size
template<typename V>
void benchmark_construct_from_range(benchmark::State& state)
{
const V src(state.range(0), 0);
V src(state.range(0), 0);

for (auto _ : state)
{
benchmark::DoNotOptimize(src);
V vec(src.begin(), src.end());
benchmark::DoNotOptimize(vec);
benchmark::ClobberMemory();
Expand All @@ -72,6 +77,8 @@ void benchmark_assign_reserved(benchmark::State& state)

for (auto _ : state)
{
benchmark::DoNotOptimize(src);

dst.clear();
benchmark::DoNotOptimize(dst);

Expand Down Expand Up @@ -113,12 +120,14 @@ BENCHMARK(benchmark_swap<small_vector<int>>)->ArgName("size")->Arg(SMALL_SIZE)->
template<typename V>
void benchmark_resize(benchmark::State& state)
{
const size_t size = state.range(0);
size_t size = state.range(0);

V vec(size);

for (auto _ : state)
{
benchmark::DoNotOptimize(size);

vec.resize(0);
benchmark::DoNotOptimize(vec);

Expand Down Expand Up @@ -236,13 +245,16 @@ void benchmark_insert_range_reserved(benchmark::State& state)
const size_t size = state.range(0);

V vec(size + 3, 1);
V rng = { 1, 2, 3 };

for (auto _ : state)
{
benchmark::DoNotOptimize(rng);

vec.resize(size);
benchmark::DoNotOptimize(vec);

vec.insert(vec.begin(), { 1, 2, 3 });
vec.insert(vec.begin(), rng.begin(), rng.end());
benchmark::DoNotOptimize(vec);

benchmark::ClobberMemory();
Expand All @@ -260,14 +272,17 @@ void benchmark_insert_range_reallocate(benchmark::State& state)
const size_t final_size = state.range(0);
const size_t start_size = small_vector<int>::inline_capacity();

V rng = { 1, 2, 3 };

for (auto _ : state)
{
V vec(start_size);

while (vec.size() < final_size)
{
benchmark::DoNotOptimize(rng);
benchmark::DoNotOptimize(vec);
vec.insert(vec.begin(), { 1, 2, 3 });
vec.insert(vec.begin(), rng.begin(), rng.end());
benchmark::ClobberMemory();
}
}
Expand Down
Loading

0 comments on commit 3e07056

Please sign in to comment.