From dec0c62997bc037bc6a88be39a6939d5a479bf1b Mon Sep 17 00:00:00 2001 From: Antonio Maiorano Date: Fri, 24 Feb 2023 20:59:08 +0000 Subject: [PATCH] tint: optimize SymbolTable::New Avoid linearly searching for prefix_i. This becomes very slow when adding the same prefix many times. Instead, cache each prefix and the last index that was assigned, and start searching from there. Note that this locally speeds up MaxLimitTests.MaxBufferBindingSize on GL backends from about 10 minutes to a few seconds. This test creates a very large struct, and Tint's GLES backend runs the PadStructs transform, which produces a struct with 16384 members. Creating these members triggers the behaviour described above when creating names for each member. Also replaced std::unordered_maps with utils::Hashmap. Change-Id: I86678a049ac229ce617d500971e9c077ff5c10a1 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/121440 Reviewed-by: Ben Clayton Commit-Queue: Antonio Maiorano Kokoro: Kokoro --- src/tint/symbol_table.cc | 44 ++++++++++++++++++++++++++-------------- src/tint/symbol_table.h | 9 ++++---- 2 files changed, 34 insertions(+), 19 deletions(-) diff --git a/src/tint/symbol_table.cc b/src/tint/symbol_table.cc index 2b20fed9a0..4f21d0be6b 100644 --- a/src/tint/symbol_table.cc +++ b/src/tint/symbol_table.cc @@ -33,9 +33,9 @@ SymbolTable& SymbolTable::operator=(SymbolTable&&) = default; Symbol SymbolTable::Register(const std::string& name) { TINT_ASSERT(Symbol, !name.empty()); - auto it = name_to_symbol_.find(name); - if (it != name_to_symbol_.end()) { - return it->second; + auto it = name_to_symbol_.Find(name); + if (it) { + return *it; } #if TINT_SYMBOL_STORE_DEBUG_NAME @@ -45,40 +45,54 @@ Symbol SymbolTable::Register(const std::string& name) { #endif ++next_symbol_; - name_to_symbol_[name] = sym; - symbol_to_name_[sym] = name; + name_to_symbol_.Add(name, sym); + symbol_to_name_.Add(sym, name); return sym; } Symbol SymbolTable::Get(const std::string& name) const { - auto it = name_to_symbol_.find(name); - return it != name_to_symbol_.end() ? it->second : Symbol(); + auto it = name_to_symbol_.Find(name); + return it ? *it : Symbol(); } std::string SymbolTable::NameFor(const Symbol symbol) const { TINT_ASSERT_PROGRAM_IDS_EQUAL(Symbol, program_id_, symbol); - auto it = symbol_to_name_.find(symbol); - if (it == symbol_to_name_.end()) { + auto it = symbol_to_name_.Find(symbol); + if (!it) { return symbol.to_str(); } - return it->second; + return *it; } Symbol SymbolTable::New(std::string prefix /* = "" */) { if (prefix.empty()) { prefix = "tint_symbol"; } - auto it = name_to_symbol_.find(prefix); - if (it == name_to_symbol_.end()) { + auto it = name_to_symbol_.Find(prefix); + if (!it) { return Register(prefix); } + + size_t i = 0; + auto last_prefix = last_prefix_to_index_.Find(prefix); + if (last_prefix) { + i = *last_prefix; + } + std::string name; - size_t i = 1; do { - name = prefix + "_" + std::to_string(i++); - } while (name_to_symbol_.count(name)); + ++i; + name = prefix + "_" + std::to_string(i); + } while (name_to_symbol_.Contains(name)); + + if (last_prefix) { + *last_prefix = i; + } else { + last_prefix_to_index_.Add(prefix, i); + } + return Register(name); } diff --git a/src/tint/symbol_table.h b/src/tint/symbol_table.h index 4881c2db99..937a764eca 100644 --- a/src/tint/symbol_table.h +++ b/src/tint/symbol_table.h @@ -16,7 +16,7 @@ #define SRC_TINT_SYMBOL_TABLE_H_ #include -#include +#include "utils/hashmap.h" #include "src/tint/symbol.h" @@ -74,7 +74,7 @@ class SymbolTable { template void Foreach(F&& callback) const { for (auto it : symbol_to_name_) { - callback(it.first, it.second); + callback(it.key, it.value); } } @@ -85,8 +85,9 @@ class SymbolTable { // The value to be associated to the next registered symbol table entry. uint32_t next_symbol_ = 1; - std::unordered_map symbol_to_name_; - std::unordered_map name_to_symbol_; + utils::Hashmap symbol_to_name_; + utils::Hashmap name_to_symbol_; + utils::Hashmap last_prefix_to_index_; tint::ProgramID program_id_; };