Skip to content

Commit 3687311

Browse files
committed
Optimized bimap using string_views
Signed-off-by: James Buckland <[email protected]>
1 parent f848464 commit 3687311

File tree

3 files changed

+27
-17
lines changed

3 files changed

+27
-17
lines changed

source/common/stats/BUILD

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ envoy_cc_library(
4242
deps = [
4343
"//include/envoy/stats:symbol_table_interface",
4444
"//source/common/common:assert_lib",
45+
"//source/common/common:utility_lib",
4546
],
4647
)
4748

source/common/stats/symbol_table_impl.cc

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,10 @@ namespace Stats {
1414
// if we can help it.
1515
StatNamePtr SymbolTableImpl::encode(const std::string& name) {
1616
SymbolVec symbol_vec;
17-
std::vector<std::string> name_vec = absl::StrSplit(name, '.');
17+
std::vector<absl::string_view> name_vec = absl::StrSplit(name, '.');
1818
symbol_vec.reserve(name_vec.size());
1919
std::transform(name_vec.begin(), name_vec.end(), std::back_inserter(symbol_vec),
20-
[this](std::string x) { return toSymbol(x); });
20+
[this](absl::string_view x) { return toSymbol(x); });
2121

2222
return std::make_unique<StatNameImpl>(symbol_vec, *this);
2323
}
@@ -35,8 +35,7 @@ void SymbolTableImpl::free(const SymbolVec& symbol_vec) {
3535
auto decode_search = decode_map_.find(symbol);
3636
RELEASE_ASSERT(decode_search != decode_map_.end(), "");
3737

38-
const std::string& str = decode_search->second;
39-
auto encode_search = encode_map_.find(str);
38+
auto encode_search = encode_map_.find(decode_search->second);
4039
RELEASE_ASSERT(encode_search != encode_map_.end(), "");
4140

4241
((encode_search->second).second)--;
@@ -50,21 +49,29 @@ void SymbolTableImpl::free(const SymbolVec& symbol_vec) {
5049
}
5150
}
5251

53-
Symbol SymbolTableImpl::toSymbol(const std::string& str) {
52+
Symbol SymbolTableImpl::toSymbol(absl::string_view sv) {
5453
Symbol result;
55-
auto encode_insert = encode_map_.insert({str, std::make_pair(current_symbol_, 1)});
56-
// If the insertion took place, we mirror the insertion in the decode_map.
57-
if (encode_insert.second) {
58-
auto decode_insert = decode_map_.insert({current_symbol_, str});
59-
// We expect the decode_map to be in lockstep.
54+
auto encode_find = encode_map_.find(sv);
55+
// If the string segment doesn't already exist,
56+
if (encode_find == encode_map_.end()) {
57+
// We create the actual string, place it in the decode_map_, and then insert a string_view
58+
// pointing to it in the encode_map_. This allows us to only store the string once.
59+
std::string str = std::string(sv.data(), sv.size());
60+
61+
auto decode_insert = decode_map_.insert({current_symbol_, std::move(str)});
6062
RELEASE_ASSERT(decode_insert.second, "");
63+
64+
auto encode_insert =
65+
encode_map_.insert({decode_insert.first->second, std::make_pair(current_symbol_, 1)});
66+
RELEASE_ASSERT(encode_insert.second, "");
67+
6168
result = current_symbol_;
6269
newSymbol();
6370
} else {
64-
// If the insertion didn't take place, return the actual value at that location
65-
result = (encode_insert.first)->second.first;
66-
// and up the refcount at that location
67-
++(encode_insert.first)->second.second;
71+
// If the insertion didn't take place, return the actual value at that location and up the
72+
// refcount at that location
73+
result = (encode_find->second).first;
74+
++(encode_find->second).second;
6875
}
6976
return result;
7077
}

source/common/stats/symbol_table_impl.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include "envoy/stats/symbol_table.h"
1212

1313
#include "common/common/assert.h"
14+
#include "common/common/utility.h"
1415

1516
#include "absl/strings/str_join.h"
1617
#include "absl/strings/str_split.h"
@@ -64,10 +65,10 @@ class SymbolTableImpl : public SymbolTable {
6465
/**
6566
* Convenience function for encode(), symbolizing one string segment at a time.
6667
*
67-
* @param str the individual string to be encoded as a symbol.
68+
* @param sv the individual string to be encoded as a symbol.
6869
* @return Symbol the encoded string.
6970
*/
70-
Symbol toSymbol(const std::string& str);
71+
Symbol toSymbol(absl::string_view sv);
7172

7273
/**
7374
* Convenience function for decode(), decoding one symbol at a time.
@@ -99,7 +100,8 @@ class SymbolTableImpl : public SymbolTable {
99100

100101
// Bimap implementation.
101102
// The encode map stores both the symbol and the ref count of that symbol.
102-
std::unordered_map<std::string, std::pair<Symbol, uint32_t>> encode_map_;
103+
// Using absl::string_view lets us only store the complete string once, in the decode map.
104+
std::unordered_map<absl::string_view, std::pair<Symbol, uint32_t>, StringViewHash> encode_map_;
103105
std::unordered_map<Symbol, std::string> decode_map_;
104106

105107
// Free pool of symbols for re-use.

0 commit comments

Comments
 (0)