| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | #include "names.h" | ||
| 2 | #include "dependencies/coz_wrap.h" | ||
| 3 | #include "logging/logging.h" | ||
| 4 | |||
| 5 | namespace lython { | ||
| 6 | |||
| 7 | std::ostream& operator<<(std::ostream& out, StringRef ref) { | ||
| 8 | 4749 | return out << StringDatabase::instance()[ref.__id__()]; | |
| 9 | } | ||
| 10 | |||
| 11 | void StringRef::print(std::ostream& out) const { | ||
| 12 |
2/2✓ Branch 1 taken 1007 times.
✓ Branch 4 taken 1007 times.
|
1007 | auto view = StringDatabase::instance()[ref]; |
| 13 |
2/2✓ Branch 2 taken 1007 times.
✓ Branch 5 taken 1007 times.
|
1007 | out << String(view); |
| 14 | 1007 | } | |
| 15 | |||
| 16 | StringRef::operator StringView() const { return StringDatabase::instance()[ref]; } | ||
| 17 | |||
| 18 | StringRef::~StringRef() { StringDatabase::instance().dec(ref); } | ||
| 19 | |||
| 20 | std::ostream& StringDatabase::report(std::ostream& out) const { | ||
| 21 | 14 | std::size_t saved = 0; | |
| 22 | 14 | std::size_t saved_up = 0; | |
| 23 | 14 | std::size_t size = 9; | |
| 24 | |||
| 25 |
1/1✓ Branch 1 taken 14 times.
|
28 | out << fmt::format( |
| 26 |
1/1✓ Branch 1 taken 14 times.
|
14 | "| {:30} | {:4} | {:4} | {:4} | {:4} | {:4} |\n", "str", "#", "use", "cpy", "low", "upp"); |
| 27 | |||
| 28 |
2/2✓ Branch 5 taken 14 times.
✓ Branch 6 taken 14 times.
|
28 | for (auto& strings: memory_blocks) { |
| 29 |
2/2✓ Branch 5 taken 4222 times.
✓ Branch 6 taken 14 times.
|
4236 | for (auto& entry: strings) { |
| 30 | 4222 | size += entry.data.size(); | |
| 31 | 4222 | auto lower = entry.data.size() * (entry.count - 1); | |
| 32 | 4222 | auto upper = entry.data.size() * (entry.copy - 1); | |
| 33 | 4222 | saved += lower; | |
| 34 | 4222 | saved_up += upper; | |
| 35 | |||
| 36 |
4/4✓ Branch 0 taken 4208 times.
✓ Branch 1 taken 14 times.
✓ Branch 2 taken 3867 times.
✓ Branch 3 taken 341 times.
|
4222 | if (entry.count == 1 && entry.in_use == 0) { |
| 37 | 3867 | continue; | |
| 38 | } | ||
| 39 | |||
| 40 | 355 | out << fmt::format("| {:30} | {:4} | {:4} | {:4} | {:4} | {:4} |\n", | |
| 41 | 355 | entry.data, | |
| 42 | 355 | entry.count, | |
| 43 | 355 | entry.in_use, | |
| 44 |
1/1✓ Branch 1 taken 355 times.
|
355 | entry.copy, |
| 45 | lower, | ||
| 46 |
1/1✓ Branch 1 taken 355 times.
|
355 | upper); |
| 47 | } | ||
| 48 | } | ||
| 49 | |||
| 50 | 14 | out << fmt::format("Size {}: {} < Saved < {} bytes (x{:6.2f} - {:6.2f})\n", | |
| 51 | size, | ||
| 52 | saved, | ||
| 53 | saved_up, | ||
| 54 | ✗ | float(size + saved) / float(size), | |
| 55 |
2/2✓ Branch 1 taken 14 times.
✓ Branch 4 taken 14 times.
|
28 | float(size + saved_up) / float(size)); |
| 56 |
2/2✓ Branch 1 taken 14 times.
✓ Branch 4 taken 14 times.
|
28 | out << fmt::format("Spent {} ms waiting on lock\n", wait_time); |
| 57 | |||
| 58 | 14 | return out; | |
| 59 | } | ||
| 60 | |||
| 61 | StringDatabase& StringDatabase::instance() { | ||
| 62 |
4/7✓ Branch 0 taken 12 times.
✓ Branch 1 taken 234966 times.
✓ Branch 3 taken 12 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 12 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
|
234978 | static StringDatabase db; |
| 63 | 234978 | return db; | |
| 64 | } | ||
| 65 | |||
| 66 | StringView StringDatabase::operator[](std::size_t i) const { | ||
| 67 | // we need to lock here in case the array gets reallocated | ||
| 68 | // during a parallel insert | ||
| 69 | #if !BUILD_WEBASSEMBLY | ||
| 70 | 64232 | StopWatch<> timer; | |
| 71 |
1/1✓ Branch 1 taken 64232 times.
|
64232 | std::lock_guard<std::recursive_mutex> guard(mu); |
| 72 |
1/1✓ Branch 1 taken 64232 times.
|
64232 | wait_time += timer.stop(); |
| 73 | #endif | ||
| 74 | |||
| 75 | assert(i < size, "array out of bound"); | ||
| 76 | |||
| 77 |
1/2✓ Branch 0 taken 64232 times.
✗ Branch 1 not taken.
|
64232 | if (i < size) { |
| 78 | 64232 | [[likely]] return get(i).data; | |
| 79 | } | ||
| 80 | |||
| 81 | ✗ | [[unlikely]] return StringView(); | |
| 82 | 64232 | } | |
| 83 | |||
| 84 | std::size_t StringDatabase::dec(std::size_t n) { | ||
| 85 |
2/2✓ Branch 0 taken 5066 times.
✓ Branch 1 taken 53980 times.
|
59046 | if (n == 0) { |
| 86 | 5066 | return n; | |
| 87 | } | ||
| 88 | |||
| 89 | #if !BUILD_WEBASSEMBLY | ||
| 90 | // we need to lock here in case the array gets reallocated during a parallel insert | ||
| 91 | 53980 | StopWatch<> timer; | |
| 92 |
1/1✓ Branch 1 taken 53980 times.
|
53980 | std::lock_guard<std::recursive_mutex> guard(mu); |
| 93 |
1/1✓ Branch 1 taken 53980 times.
|
53980 | wait_time += timer.stop(); |
| 94 | #endif | ||
| 95 | |||
| 96 | // Easiest way to keep track of every StringRef in the code | ||
| 97 | 53980 | auto& entry = get(n); | |
| 98 | 53980 | entry.in_use -= 1; | |
| 99 | 53980 | entry.copy += 1; | |
| 100 | |||
| 101 | 53980 | return n; | |
| 102 | 53980 | } | |
| 103 | |||
| 104 | std::size_t StringDatabase::inc(std::size_t i) { | ||
| 105 |
2/2✓ Branch 0 taken 5054 times.
✓ Branch 1 taken 39703 times.
|
44757 | if (i == 0) { |
| 106 | 5054 | return i; | |
| 107 | } | ||
| 108 | |||
| 109 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 39703 times.
|
39703 | if (i >= size) { |
| 110 | kwdebug("Critical error {} < {}", i, size); | ||
| 111 | ✗ | return 0; | |
| 112 | } | ||
| 113 | |||
| 114 | #if !BUILD_WEBASSEMBLY | ||
| 115 | // we need to lock here in case the array gets reallocated during a parallel insert | ||
| 116 | 39703 | StopWatch<> timer; | |
| 117 |
1/1✓ Branch 1 taken 39703 times.
|
39703 | std::lock_guard<std::recursive_mutex> guard(mu); |
| 118 |
1/1✓ Branch 1 taken 39703 times.
|
39703 | wait_time += timer.stop(); |
| 119 | #endif | ||
| 120 | |||
| 121 | 39703 | get(i).in_use += 1; | |
| 122 | 39703 | return i; | |
| 123 | 39703 | }; | |
| 124 | |||
| 125 | Array<StringDatabase::StringEntry>& StringDatabase::current_block() { | ||
| 126 | 3679 | Array<StringEntry>& last = *memory_blocks.rbegin(); | |
| 127 | |||
| 128 |
1/2✓ Branch 2 taken 3679 times.
✗ Branch 3 not taken.
|
3679 | if (last.capacity() != last.size()) |
| 129 | 3679 | return last; | |
| 130 | |||
| 131 | ✗ | return newblock(); | |
| 132 | } | ||
| 133 | |||
| 134 | StringRef StringDatabase::string(String const& name) { | ||
| 135 | COZ_BEGIN("T::StringDatabase::string"); | ||
| 136 | 13498 | auto str = lookup_or_insert_string(name); | |
| 137 | |||
| 138 | COZ_PROGRESS_NAMED("StringDatabase::string"); | ||
| 139 | COZ_END("T::StringDatabase::string"); | ||
| 140 | 13498 | return str; | |
| 141 | } | ||
| 142 | |||
| 143 | StringRef StringDatabase::insert_string(String const& name) { | ||
| 144 | COZ_BEGIN("T::StringDatabase::insert"); | ||
| 145 | 3679 | std::size_t id = size; | |
| 146 |
1/1✓ Branch 1 taken 3679 times.
|
3679 | auto& strings = current_block(); |
| 147 | 3679 | std::size_t n = strings.size(); | |
| 148 | |||
| 149 | 3679 | strings.push_back({name, 1, 0, 1}); | |
| 150 | 3679 | StringView str = strings[n].data; | |
| 151 | |||
| 152 |
1/1✓ Branch 1 taken 3679 times.
|
3679 | defined[str] = {id}; |
| 153 | 3679 | size += 1; | |
| 154 | |||
| 155 | COZ_PROGRESS_NAMED("StringDatabase::insert"); | ||
| 156 | COZ_END("T::StringDatabase::insert"); | ||
| 157 |
1/1✓ Branch 1 taken 3679 times.
|
7358 | return StringRef(id); |
| 158 | 3679 | } | |
| 159 | |||
| 160 | StringRef StringDatabase::lookup_or_insert_string(String const& name) { | ||
| 161 | |||
| 162 | #if !BUILD_WEBASSEMBLY | ||
| 163 | 13498 | StopWatch<> timer; | |
| 164 |
1/1✓ Branch 1 taken 13498 times.
|
13498 | std::lock_guard<std::recursive_mutex> guard(mu); |
| 165 |
1/1✓ Branch 1 taken 13498 times.
|
13498 | wait_time += timer.stop(); |
| 166 | #endif | ||
| 167 | |||
| 168 |
1/1✓ Branch 2 taken 13498 times.
|
13498 | auto val = defined.find(name); |
| 169 | |||
| 170 |
2/2✓ Branch 2 taken 3679 times.
✓ Branch 3 taken 9819 times.
|
13498 | if (val == defined.end()) { |
| 171 |
1/1✓ Branch 1 taken 3679 times.
|
3679 | return insert_string(name); |
| 172 | } | ||
| 173 | |||
| 174 | 9819 | auto ref = val->second; | |
| 175 |
1/1✓ Branch 2 taken 9819 times.
|
9819 | auto entry = get(ref); |
| 176 | 9819 | entry.count += 1; | |
| 177 | 9819 | entry.in_use += 1; | |
| 178 | |||
| 179 |
1/1✓ Branch 1 taken 9819 times.
|
9819 | return StringRef(ref); |
| 180 | 13498 | } | |
| 181 | |||
| 182 | Array<StringDatabase::StringEntry>& StringDatabase::newblock() { | ||
| 183 |
1/1✓ Branch 2 taken 12 times.
|
12 | memory_blocks.push_back(Array<StringEntry>()); |
| 184 | 12 | Array<StringEntry>& last = *memory_blocks.rbegin(); | |
| 185 | 12 | last.reserve(block_size); | |
| 186 |
1/1✓ Branch 1 taken 12 times.
|
12 | reverse.push_back(&last); |
| 187 | 12 | return last; | |
| 188 | } | ||
| 189 | |||
| 190 | StringDatabase::StringDatabase() { | ||
| 191 | |||
| 192 |
1/1✓ Branch 1 taken 12 times.
|
12 | auto& block = newblock(); |
| 193 | 12 | block.push_back({"", 0, 0}); | |
| 194 | 12 | StringView str = block[0].data; | |
| 195 | |||
| 196 |
1/1✓ Branch 1 taken 12 times.
|
12 | defined[str] = {0}; |
| 197 | 12 | size = 1; | |
| 198 | 36 | } | |
| 199 | |||
| 200 | } // namespace lython | ||
| 201 |