Skip to content

perf(registry): O(1) symbol row lookup#1847

Open
trollixx wants to merge 1 commit intozealdocs:mainfrom
trollixx:perf-registry-indexable-symbols
Open

perf(registry): O(1) symbol row lookup#1847
trollixx wants to merge 1 commit intozealdocs:mainfrom
trollixx:perf-registry-indexable-symbols

Conversation

@trollixx
Copy link
Copy Markdown
Member

@trollixx trollixx commented May 7, 2026

Summary by CodeRabbit

  • Refactor
    • Optimized internal symbol storage and data access mechanisms for improved efficiency.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 7, 2026

Review Change Stack

Walkthrough

The PR refactors symbol storage in Docset from QMultiMap<QString, QUrl> to QList<std::pair<QString, QUrl>>, updating the public API return type, internal cache member type, loading logic, and all consumer code that accesses symbols. The lazy-loading and caching behavior remain semantically unchanged.

Changes

Symbol Storage Container Refactoring

Layer / File(s) Summary
Data Structure Contracts
src/libs/registry/docset.h
Header adds <utility> include. Docset::symbols() return type changes from const QMultiMap<QString, QUrl> & to const QList<std::pair<QString, QUrl>> &. Internal m_symbols member type changes from QMap<QString, QMultiMap<QString, QUrl>> to QMap<QString, QList<std::pair<QString, QUrl>>>.
Symbol Loading Implementation
src/libs/registry/docset.cpp
symbols() accessor signature updated to return list reference; lazy-loading behavior unchanged. loadSymbols() populates the list-based cache by appending (name, url) pairs via emplace_back() instead of inserting into a multimap.
ListModel Symbol Access
src/libs/registry/listmodel.cpp
ListModel::data() symbol lookups switch from iterator-based std::advance() traversal to direct random-access indexing: .at(index.row()).first for symbol names and .at(index.row()).second for URLs.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title 'perf(registry): O(1) symbol row lookup' directly and clearly describes the main performance optimization: replacing QMultiMap with QList to enable O(1) random access for symbol lookups instead of O(n) iteration.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 Microsoft Presidio Analyzer (2.2.362)
src/libs/registry/docset.cpp

Microsoft Presidio Analyzer failed to scan this file


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@codacy-production
Copy link
Copy Markdown

Up to standards ✅

🟢 Issues 0 issues

Results:
0 new issues

View in Codacy

NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
src/libs/registry/docset.cpp (2)

304-310: 🧹 Nitpick | 🔵 Trivial | 💤 Low value

QMap::operator[] in a const method silently inserts an empty list for unknown symbol types.

When symbolType is not in m_symbolStrings, loadSymbols(symbolType) is a no-op, so m_symbols still doesn't contain the key after the call. Line 309 then uses the non-const operator[] (permitted because m_symbols is mutable) which inserts a default-constructed QList, acting as negative caching. This is semantically correct but can be made explicit by first calling loadSymbols, which already creates the entry in the two-arg overload, or by using find/constFind to avoid the implicit insertion. At minimum, a comment explaining the intentional negative-cache insertion would prevent future confusion.

♻️ Proposed clarification — use `find` to make intent explicit
 const QList<std::pair<QString, QUrl>> &Docset::symbols(const QString &symbolType) const
 {
     if (!m_symbols.contains(symbolType)) {
         loadSymbols(symbolType);
+        // Ensure an entry exists even if symbolType has no DB aliases (negative cache).
+        m_symbols[symbolType]; // default-constructs empty list if still absent
     }
-    return m_symbols[symbolType];
+    return *m_symbols.find(symbolType);
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/libs/registry/docset.cpp` around lines 304 - 310, The Docset::symbols
const method currently uses m_symbols[symbolType] which, due to m_symbols being
mutable, silently inserts a default QList for unknown keys; update the method to
avoid implicit insertion by first calling loadSymbols(symbolType) and then
retrieving the entry with m_symbols.constFind(symbolType) (or
m_symbols.find/check contains) and return the found const reference if present,
otherwise return a static empty QList reference; mention or adjust loadSymbols
and m_symbolStrings usage so the two-arg overload still creates entries when
intended to preserve explicit negative-caching behavior.

528-567: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Sorting regression: multi-alias symbol types will no longer be globally sorted.

The old QMultiMap guaranteed global sort order by key across all insertions. The new code calls loadSymbols(symbolType, symbolString) once per raw DB alias (e.g., all of "dcop", "func", "ffunc", "signal", "slot", … for the canonical "Function" type) and appends each query's ORDER BY name result to the same QList. With QMultiMap, the items are always sorted by key, so inserting from multiple queries still yielded a globally sorted list. With sequential emplace_back appends the final list is only sorted within each alias's batch — not across batches — breaking alphabetical order in the symbol panel for any canonical type that has more than one raw DB alias.

🐛 Proposed fix — sort after all batches are appended (one-arg overload)
 void Docset::loadSymbols(const QString &symbolType) const
 {
     for (auto it = std::as_const(m_symbolStrings).equal_range(symbolType); it.first != it.second; ++it.first) {
         loadSymbols(symbolType, it.first.value());
     }
+
+    // Re-sort across alias batches; each batch is already sorted by the SQL ORDER BY,
+    // but multiple batches are appended sequentially, not merged.
+    auto &list = m_symbols[symbolType];
+    std::sort(list.begin(), list.end(),
+              [](const auto &a, const auto &b) { return a.first < b.first; });
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/libs/registry/docset.cpp` around lines 528 - 567, The one-argument
overload Docset::loadSymbols(const QString &symbolType) appends multiple alias
batches into m_symbols[symbolType] without preserving a global sort; after the
loop that calls loadSymbols(symbolType, it.first.value()), obtain a reference to
QList<std::pair<QString,QUrl>>& symbols = m_symbols[symbolType] and sort it once
(e.g. use std::sort with a lambda that compares the pair.first QStrings via
QString::localeAwareCompare or QString::compare) to restore global alphabetical
order across all alias batches.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@src/libs/registry/docset.cpp`:
- Around line 304-310: The Docset::symbols const method currently uses
m_symbols[symbolType] which, due to m_symbols being mutable, silently inserts a
default QList for unknown keys; update the method to avoid implicit insertion by
first calling loadSymbols(symbolType) and then retrieving the entry with
m_symbols.constFind(symbolType) (or m_symbols.find/check contains) and return
the found const reference if present, otherwise return a static empty QList
reference; mention or adjust loadSymbols and m_symbolStrings usage so the
two-arg overload still creates entries when intended to preserve explicit
negative-caching behavior.
- Around line 528-567: The one-argument overload Docset::loadSymbols(const
QString &symbolType) appends multiple alias batches into m_symbols[symbolType]
without preserving a global sort; after the loop that calls
loadSymbols(symbolType, it.first.value()), obtain a reference to
QList<std::pair<QString,QUrl>>& symbols = m_symbols[symbolType] and sort it once
(e.g. use std::sort with a lambda that compares the pair.first QStrings via
QString::localeAwareCompare or QString::compare) to restore global alphabetical
order across all alias batches.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: dff2f217-2c67-4634-86dc-0700b7f221c6

📥 Commits

Reviewing files that changed from the base of the PR and between dcb9817 and cea2577.

📒 Files selected for processing (3)
  • src/libs/registry/docset.cpp
  • src/libs/registry/docset.h
  • src/libs/registry/listmodel.cpp

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant