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 <bclayton@google.com>
Commit-Queue: Antonio Maiorano <amaiorano@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
This commit is contained in:
Antonio Maiorano 2023-02-24 20:59:08 +00:00 committed by Dawn LUCI CQ
parent 66d487395d
commit dec0c62997
2 changed files with 34 additions and 19 deletions

View File

@ -33,9 +33,9 @@ SymbolTable& SymbolTable::operator=(SymbolTable&&) = default;
Symbol SymbolTable::Register(const std::string& name) { Symbol SymbolTable::Register(const std::string& name) {
TINT_ASSERT(Symbol, !name.empty()); TINT_ASSERT(Symbol, !name.empty());
auto it = name_to_symbol_.find(name); auto it = name_to_symbol_.Find(name);
if (it != name_to_symbol_.end()) { if (it) {
return it->second; return *it;
} }
#if TINT_SYMBOL_STORE_DEBUG_NAME #if TINT_SYMBOL_STORE_DEBUG_NAME
@ -45,40 +45,54 @@ Symbol SymbolTable::Register(const std::string& name) {
#endif #endif
++next_symbol_; ++next_symbol_;
name_to_symbol_[name] = sym; name_to_symbol_.Add(name, sym);
symbol_to_name_[sym] = name; symbol_to_name_.Add(sym, name);
return sym; return sym;
} }
Symbol SymbolTable::Get(const std::string& name) const { Symbol SymbolTable::Get(const std::string& name) const {
auto it = name_to_symbol_.find(name); auto it = name_to_symbol_.Find(name);
return it != name_to_symbol_.end() ? it->second : Symbol(); return it ? *it : Symbol();
} }
std::string SymbolTable::NameFor(const Symbol symbol) const { std::string SymbolTable::NameFor(const Symbol symbol) const {
TINT_ASSERT_PROGRAM_IDS_EQUAL(Symbol, program_id_, symbol); TINT_ASSERT_PROGRAM_IDS_EQUAL(Symbol, program_id_, symbol);
auto it = symbol_to_name_.find(symbol); auto it = symbol_to_name_.Find(symbol);
if (it == symbol_to_name_.end()) { if (!it) {
return symbol.to_str(); return symbol.to_str();
} }
return it->second; return *it;
} }
Symbol SymbolTable::New(std::string prefix /* = "" */) { Symbol SymbolTable::New(std::string prefix /* = "" */) {
if (prefix.empty()) { if (prefix.empty()) {
prefix = "tint_symbol"; prefix = "tint_symbol";
} }
auto it = name_to_symbol_.find(prefix); auto it = name_to_symbol_.Find(prefix);
if (it == name_to_symbol_.end()) { if (!it) {
return Register(prefix); 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; std::string name;
size_t i = 1;
do { do {
name = prefix + "_" + std::to_string(i++); ++i;
} while (name_to_symbol_.count(name)); 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); return Register(name);
} }

View File

@ -16,7 +16,7 @@
#define SRC_TINT_SYMBOL_TABLE_H_ #define SRC_TINT_SYMBOL_TABLE_H_
#include <string> #include <string>
#include <unordered_map> #include "utils/hashmap.h"
#include "src/tint/symbol.h" #include "src/tint/symbol.h"
@ -74,7 +74,7 @@ class SymbolTable {
template <typename F> template <typename F>
void Foreach(F&& callback) const { void Foreach(F&& callback) const {
for (auto it : symbol_to_name_) { 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. // The value to be associated to the next registered symbol table entry.
uint32_t next_symbol_ = 1; uint32_t next_symbol_ = 1;
std::unordered_map<Symbol, std::string> symbol_to_name_; utils::Hashmap<Symbol, std::string, 0> symbol_to_name_;
std::unordered_map<std::string, Symbol> name_to_symbol_; utils::Hashmap<std::string, Symbol, 0> name_to_symbol_;
utils::Hashmap<std::string, size_t, 0> last_prefix_to_index_;
tint::ProgramID program_id_; tint::ProgramID program_id_;
}; };