diff --git a/src/libexpr/include/nix/expr/symbol-table.hh b/src/libexpr/include/nix/expr/symbol-table.hh index 018465bf5..c04cc041b 100644 --- a/src/libexpr/include/nix/expr/symbol-table.hh +++ b/src/libexpr/include/nix/expr/symbol-table.hh @@ -81,26 +81,29 @@ public: class SymbolTable { private: - std::unordered_map> symbols; + /** + * Map from string view (backed by ChunkedVector) -> offset into the store. + * ChunkedVector references are never invalidated. + */ + std::unordered_map symbols; ChunkedVector store{16}; public: /** - * converts a string into a symbol. + * Converts a string into a symbol. */ Symbol create(std::string_view s) { // Most symbols are looked up more than once, so we trade off insertion performance // for lookup performance. - // TODO: could probably be done more efficiently with transparent Hash and Equals - // on the original implementation using unordered_set // FIXME: make this thread-safe. auto it = symbols.find(s); - if (it != symbols.end()) return Symbol(it->second.second + 1); + if (it != symbols.end()) + return Symbol(it->second + 1); - const auto & [rawSym, idx] = store.add(std::string(s)); - symbols.emplace(rawSym, std::make_pair(&rawSym, idx)); + const auto & [rawSym, idx] = store.add(s); + symbols.emplace(rawSym, idx); return Symbol(idx + 1); } diff --git a/src/libutil/include/nix/util/chunked-vector.hh b/src/libutil/include/nix/util/chunked-vector.hh index 96a717556..2c21183ac 100644 --- a/src/libutil/include/nix/util/chunked-vector.hh +++ b/src/libutil/include/nix/util/chunked-vector.hh @@ -45,9 +45,10 @@ public: addChunk(); } - uint32_t size() const { return size_; } + uint32_t size() const noexcept { return size_; } - std::pair add(T value) + template + std::pair add(Args &&... args) { const auto idx = size_++; auto & chunk = [&] () -> auto & { @@ -55,11 +56,16 @@ public: return back; return addChunk(); }(); - auto & result = chunk.emplace_back(std::move(value)); + auto & result = chunk.emplace_back(std::forward(args)...); return {result, idx}; } - const T & operator[](uint32_t idx) const + /** + * Unchecked subscript operator. + * @pre add must have been called at least idx + 1 times. + * @throws nothing + */ + const T & operator[](uint32_t idx) const noexcept { return chunks[idx / ChunkSize][idx % ChunkSize]; }