Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions source/common/stats/symbol_table.cc
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,12 @@ void SymbolTable::Encoding::appendToMemBlock(StatName stat_name,
}
}

void SymbolTable::Encoding::appendStatNameDataTo(StatName stat_name,
MemBlockBuilder<uint8_t>& mem_block) {
auto sv = stat_name.dataAsStringView();
mem_block.appendData(absl::MakeSpan(reinterpret_cast<const uint8_t*>(sv.data()), sv.size()));
}

SymbolTable::SymbolTable()
// Have to be explicitly initialized, if we want to use the ABSL_GUARDED_BY macro.
: next_symbol_(FirstValidSymbol), monotonic_counter_(FirstValidSymbol) {}
Expand Down Expand Up @@ -551,7 +557,7 @@ StatNameStorage::StatNameStorage(absl::string_view name, SymbolTable& table)
StatNameStorage::StatNameStorage(StatName src, SymbolTable& table) {
const size_t size = src.size();
MemBlockBuilder<uint8_t> storage(size); // Note: MemBlockBuilder takes uint64_t.
src.copyToMemBlock(storage);
SymbolTable::Encoding::appendToMemBlock(src, storage);
setBytes(storage.release());
table.incRefCount(statName());
}
Expand Down Expand Up @@ -666,7 +672,7 @@ SymbolTable::StoragePtr SymbolTable::join(const StatNameVec& stat_names) const {
MemBlockBuilder<uint8_t> mem_block(Encoding::totalSizeBytes(num_bytes));
Encoding::appendEncoding(num_bytes, mem_block);
for (StatName stat_name : stat_names) {
stat_name.appendDataToMemBlock(mem_block);
Encoding::appendStatNameDataTo(stat_name, mem_block);
}
ASSERT(mem_block.capacityRemaining() == 0);
return mem_block.release();
Expand Down
43 changes: 15 additions & 28 deletions source/common/stats/symbol_table.h
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,14 @@ class SymbolTable final {
*/
static void appendEncoding(uint64_t number, MemBlockBuilder<uint8_t>& mem_block);

/**
* Appends stat_name's data into storage.
*
* @param stat_name the stat_name to append.
* @param mem_block the memory block to append to.
*/
static void appendStatNameDataTo(StatName stat_name, MemBlockBuilder<uint8_t>& mem_block);

/**
* Appends stat_name's bytes into mem_block, which must have been allocated to
* allow for stat_name.size() bytes.
Expand Down Expand Up @@ -633,36 +641,15 @@ class StatName {
size_t dataSize() const { return dataAsStringView().size(); }

/**
* @return size_t the number of bytes in the symbol array, including the
* overhead for the size itself.
* @return size_t the number of bytes in the symbol array, including the overhead for the size
* itself. NOTE: this will return at least one byte even when there is no backing storage, to
* indicate the encoded length prefix when encoding the StatName into a StatNameList and so on.
* However, you can NEVER assume that data()/dataIncludingSize() will return non-nullptr just
* because this returns non-zero; the empty()/dataSize() APIs should be used to check whether the
* StatName has valid data.
*/
size_t size() const { return SymbolTable::Encoding::totalSizeBytes(dataSize()); }

/**
* Copies the entire StatName representation into a MemBlockBuilder, including
* the length metadata at the beginning. The MemBlockBuilder must not have
* any other data in it.
*
* @param mem_block_builder the builder to receive the storage.
*/
void copyToMemBlock(MemBlockBuilder<uint8_t>& mem_block_builder) {
ASSERT(mem_block_builder.size() == 0);
mem_block_builder.appendData(absl::MakeSpan(size_and_data_, size()));
}
Comment on lines -641 to -651
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This method doesn't take the special case where size_and_data_ be null take into account. At that case the size() will return 1, but the size_and_data_ is null, then crash. The Encoding::appendToMemBlock have handled that correctly. So we remove this method and reuse the Encoding::appendToMemBlock.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we just document this and add an ASSERT? This is a pretty big change for a corner-case, especially un-inlining a performance critical function.


/**
* Appends the data portion of the StatName representation into a
* MemBlockBuilder, excluding the length metadata. This is appropriate for
* join(), where several stat-names are combined, and we only need the
* aggregated length metadata.
*
* @param mem_block_builder the builder to receive the storage.
*/
void appendDataToMemBlock(MemBlockBuilder<uint8_t>& storage) {
auto sv = dataAsStringView();
storage.appendData(absl::MakeSpan(reinterpret_cast<const uint8_t*>(sv.data()), sv.size()));
}
Comment on lines -653 to -664
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To keep consistence, we move this logic to Encoding as a helper method.


#ifndef ENVOY_CONFIG_COVERAGE
void debugPrint();
#endif
Expand Down Expand Up @@ -695,7 +682,6 @@ class StatName {
*/
bool startsWith(StatName symbolic_prefix) const;

Comment thread
wbpcode marked this conversation as resolved.
private:
/**
* Casts the raw data as a string_view, decoding the varint length prefix.
* All accessors that need the data pointer and/or size should delegate to
Expand All @@ -709,6 +695,7 @@ class StatName {
return {reinterpret_cast<const char*>(size_and_data_ + prefix_size), data_size};
}

private:
const uint8_t* size_and_data_{nullptr};
Comment thread
wbpcode marked this conversation as resolved.
};

Expand Down
9 changes: 9 additions & 0 deletions test/common/stats/symbol_table_impl_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -701,6 +701,15 @@ TEST_F(StatNameTest, StorageCopy) {
EXPECT_NE(a.data(), c.data());
}

TEST_F(StatNameTest, StorageFromEmptyStatName) {
StatName empty;
StatNameStorage b_storage(empty, table_);
const StatName b = b_storage.statName();
EXPECT_EQ(empty, b);
EXPECT_NE(empty.data(), b.data());
b_storage.free(table_);
}

TEST_F(StatNameTest, AddingToPoolViaStatNamePreservesDynamicSegments) {
const StatNameDynamicStorage tag_name("tag", table_);
const StatNameDynamicStorage tag_value("value", table_);
Expand Down
Loading