OLD | NEW |
(Empty) | |
| 1 // Copyright 2017 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "base/containers/flat_set.h" |
| 6 |
| 7 #include <algorithm> |
| 8 #include <numeric> |
| 9 #include <random> |
| 10 #include <string> |
| 11 #include <vector> |
| 12 |
| 13 #include "base/memory/ptr_util.h" |
| 14 #include "base/strings/string_piece.h" |
| 15 #include "base/time/time.h" |
| 16 #include "testing/gtest/include/gtest/gtest.h" |
| 17 #include "testing/perf/perf_test.h" |
| 18 |
| 19 namespace base { |
| 20 enum class TestOrder { ASCENDING, DESCENDING, INTERLEAVED, RANDOM }; |
| 21 |
| 22 enum class InputRelation { SMALLER, GREATER }; |
| 23 |
| 24 std::string to_string(TestOrder order) { |
| 25 switch (order) { |
| 26 case TestOrder::ASCENDING: |
| 27 return "ascending"; |
| 28 case TestOrder::DESCENDING: |
| 29 return "descending"; |
| 30 case TestOrder::INTERLEAVED: |
| 31 return "interleaved"; |
| 32 case TestOrder::RANDOM: |
| 33 return "random"; |
| 34 default: |
| 35 return ""; |
| 36 } |
| 37 } |
| 38 |
| 39 std::string to_string(InputRelation rel) { |
| 40 switch (rel) { |
| 41 case InputRelation::SMALLER: |
| 42 return "smaller"; |
| 43 case InputRelation::GREATER: |
| 44 return "greater"; |
| 45 default: |
| 46 return ""; |
| 47 } |
| 48 } |
| 49 |
| 50 std::string to_string(RangeInsertMethod method) { |
| 51 switch (method) { |
| 52 case RangeInsertMethod::ONE_BY_ONE: |
| 53 return "One By One"; |
| 54 case RangeInsertMethod::STABLE_SORT_ALL: |
| 55 return "Stable Sort All"; |
| 56 case RangeInsertMethod::STABLE_SORT_SMART: |
| 57 return "Stable Sort Smart"; |
| 58 case RangeInsertMethod::STABLE_SORT_SMARTER: |
| 59 return "Stable Sort Smarter"; |
| 60 default: |
| 61 return ""; |
| 62 } |
| 63 } |
| 64 |
| 65 std::vector<int> GetInputs(int length, TestOrder order, int start = 0) { |
| 66 std::vector<int> inputs(length); |
| 67 std::iota(std::begin(inputs), std::end(inputs), start); |
| 68 |
| 69 switch (order) { |
| 70 case TestOrder::ASCENDING: |
| 71 break; |
| 72 case TestOrder::DESCENDING: |
| 73 std::reverse(std::begin(inputs), std::end(inputs)); |
| 74 break; |
| 75 case TestOrder::INTERLEAVED: |
| 76 for (int i = 0; i < length / 2; i += 2) |
| 77 std::swap(inputs[i], inputs[length - 1 - i]); |
| 78 break; |
| 79 case TestOrder::RANDOM: { |
| 80 std::random_device rd; |
| 81 std::mt19937 g(rd()); |
| 82 std::shuffle(std::begin(inputs), std::end(inputs), g); |
| 83 break; |
| 84 } |
| 85 } |
| 86 |
| 87 return inputs; |
| 88 } |
| 89 |
| 90 void test_range_insertion(int initial_size, |
| 91 int n_items, |
| 92 int pct_overlap, |
| 93 InputRelation rel, |
| 94 TestOrder order, |
| 95 RangeInsertMethod method) { |
| 96 int set_start = 0; |
| 97 int input_start = 0; |
| 98 |
| 99 if (rel == InputRelation::SMALLER) { |
| 100 set_start = std::max(0.0, n_items - pct_overlap / 100.0 * initial_size); |
| 101 } else { |
| 102 input_start = std::max(0.0, initial_size - pct_overlap / 100.0 * n_items); |
| 103 } |
| 104 |
| 105 flat_set<int> set(GetInputs(initial_size, TestOrder::ASCENDING, set_start), |
| 106 KEEP_FIRST_OF_DUPES); |
| 107 std::string description = "Initial Size: " + std::to_string(initial_size) + |
| 108 "\tNumber of Items: " + std::to_string(n_items) + |
| 109 "\tPct Overlap: " + std::to_string(pct_overlap) + |
| 110 "\tInputRelation: " + to_string(rel) + |
| 111 "\tTestOrder: " + to_string(order) + |
| 112 "\tMethod: " + to_string(method); |
| 113 std::vector<int> inputs = GetInputs(n_items, order, input_start); |
| 114 TimeTicks start = TimeTicks::Now(); |
| 115 set.insert(inputs.begin(), inputs.end(), method); |
| 116 TimeTicks end = TimeTicks::Now(); |
| 117 double duration = (end - start).InMicroseconds(); |
| 118 perf_test::PrintResult("RangeInsertionTest", "", description, duration, "us", |
| 119 true); |
| 120 } |
| 121 |
| 122 void test_insert_single_close_to_end(int n_items, RangeInsertMethod method) { |
| 123 std::vector<int> inputs = GetInputs(n_items, TestOrder::ASCENDING); |
| 124 |
| 125 std::string description = "Number of Items: " + std::to_string(n_items) + |
| 126 "\tMethod: " + to_string(method); |
| 127 flat_set<int> set; |
| 128 set.insert(inputs.back()); |
| 129 TimeTicks start = TimeTicks::Now(); |
| 130 for (auto iter = inputs.begin(); std::next(iter) != inputs.end(); ++iter) { |
| 131 set.insert(iter, std::next(iter), method); |
| 132 } |
| 133 TimeTicks end = TimeTicks::Now(); |
| 134 double duration = (end - start).InMicroseconds(); |
| 135 perf_test::PrintResult("RangeInsertionTest", "", description, duration, "us", |
| 136 true); |
| 137 } |
| 138 |
| 139 TEST(FlatSetPerfTest, RangeInsertionTest) { |
| 140 for (int i = 0; i < 16; ++i) { |
| 141 for (int n = 0; n < 16; ++n) { |
| 142 for (int o = 0; o <= 10; ++o) { |
| 143 for (int r = 0; r < 2; ++r) { |
| 144 for (int t = 0; t < 4; ++t) { |
| 145 for (int m = 0; m < 4; ++m) { |
| 146 test_range_insertion( |
| 147 1 << i, 1 << n, o * 10, static_cast<InputRelation>(r), |
| 148 static_cast<TestOrder>(t), static_cast<RangeInsertMethod>(m)); |
| 149 } |
| 150 } |
| 151 } |
| 152 } |
| 153 } |
| 154 } |
| 155 } |
| 156 |
| 157 TEST(FlatSetPerfTest, SingleRangeInsertionTestCloseToEnd) { |
| 158 for (int i = 0; i < 16; ++i) { |
| 159 for (int m : {0, 1, 2, 3}) { |
| 160 test_insert_single_close_to_end(1 << i, |
| 161 static_cast<RangeInsertMethod>(m)); |
| 162 } |
| 163 } |
| 164 } |
| 165 |
| 166 } // namespace base |
OLD | NEW |