Skip to content

perf(activity): cache singleton pointers and avoid string concat in hot path#9997

Open
qoole wants to merge 1 commit into
nextcloud:masterfrom
qoole:perf/activity-list-allocations
Open

perf(activity): cache singleton pointers and avoid string concat in hot path#9997
qoole wants to merge 1 commit into
nextcloud:masterfrom
qoole:perf/activity-list-allocations

Conversation

@qoole
Copy link
Copy Markdown
Contributor

@qoole qoole commented May 7, 2026

Summary

Three small allocation/dereference cleanups in the activity list and user model. Each one is per-row or per-refresh, and the activity list data() runs on every visible row of every model update.

ActivityListModel::data — cache FolderMan::instance()

Two places in data() dereference the FolderMan singleton twice in succession:

const auto folder = FolderMan::instance()->folder(...);
...
const auto localFiles = FolderMan::instance()->findFileInLocalFolders(...);

Cached the pointer once per role evaluation. Same behavior, half the singleton lookups.

ActivityListModel::convertLinkToActionButton — reply icon URL

Two improvements bundled:

  1. The replyButtonPath was constructed unconditionally even when isReplyIconApplicable is false. Moved inside the branch.
  2. The path was built as QStringLiteral(".../reply.svg") + "/", allocating a QString concat every call. Baked the trailing slash into the literal so it's a single immutable QStringLiteral.

Same URL on the wire; one allocation removed per applicable activity link.

User::slotRefresh — cache _account.data()

slotRefresh was calling _account.data() five times in a row. Cached once into a local auto *account. Behavior identical (the smart pointer is already strong-rooted on this->_account for the duration of the function).

Checklist

AI (if applicable)

  • The content of this PR was partly or fully generated using AI

Comment thread src/gui/tray/activitylistmodel.cpp Outdated
Comment on lines +153 to +154
auto *folderMan = FolderMan::instance();
const auto folder = folderMan->folder(activity._folder);
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

why not make FolderMan::instance() an inline function if we think this is overused and may lead to overhead ?
would not increase code complexity

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done in 8a10051 — made FolderMan::instance() an inline accessor in the header instead of caching the pointer locally. Removes the call overhead everywhere without the local-variable change.

Comment thread src/gui/tray/activitylistmodel.cpp Outdated
if (isReplyIconApplicable) {
activityLinkCopy._imageSource = QString(replyButtonPath + "/");
activityLinkCopy._imageSourceHovered = QString(replyButtonPath + "/");
const QString replyButtonPath = QStringLiteral("image://svgimage-custom-color/reply.svg/");
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

would be much better to use a string literal to generate a proper QString

Suggested change
const QString replyButtonPath = QStringLiteral("image://svgimage-custom-color/reply.svg/");
using namespace Qt::StringLiterals;
const auto replyButtonPath = u"image://svgimage-custom-color/reply.svg/"_s;

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Applied your suggestion in 8a10051 (u"..."_s string literal).

Comment thread src/gui/tray/usermodel.cpp Outdated
{
slotRefreshUserStatus();

auto *account = _account.data();
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

AccountPtr::data() is an inline method
your changes will not bring any difference from performance point of view
please revert the changes around _account.data() use

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Reverted in 8a10051_account.data() usage in usermodel.cpp is back to the original.

@github-actions
Copy link
Copy Markdown

Hello there,
Thank you so much for taking the time and effort to create a pull request to our Nextcloud project.

We hope that the review process is going smooth and is helpful for you. We want to ensure your pull request is reviewed to your satisfaction. If you have a moment, our community management team would very much appreciate your feedback on your experience with this PR review process.

Your feedback is valuable to us as we continuously strive to improve our community developer experience. Please take a moment to complete our short survey by clicking on the following link: https://cloud.nextcloud.com/apps/forms/s/i9Ago4EQRZ7TWxjfmeEpPkf6

Thank you for contributing to Nextcloud and we hope to hear from you soon!

(If you believe you should not receive this message, you can add yourself to the blocklist.)

@qoole qoole force-pushed the perf/activity-list-allocations branch from 95ab3f7 to 702b65c Compare May 26, 2026 19:19
…in hot path

- FolderMan::instance(): make it an inline accessor returning the static
  pointer, removing the out-of-line call overhead at every use site
  without adding any local caching or extra complexity.
- ActivityListModel::convertLinkToActionButton: move the reply icon URL
  construction inside the isReplyIconApplicable branch and bake the
  trailing slash into the string literal so the path is a single
  immutable QString instead of two QString::operator+ allocations.

Signed-off-by: Qoole <[email protected]>
@qoole qoole force-pushed the perf/activity-list-allocations branch from 702b65c to 8a10051 Compare May 26, 2026 19:20
@qoole
Copy link
Copy Markdown
Contributor Author

qoole commented May 26, 2026

Addressed in 8a10051:

  • Made FolderMan::instance() an inline accessor in the header (no local caching, no added complexity).
  • Reverted the _account.data() changes in usermodel.cpp.
  • Applied the u"..."_s string-literal suggestion in convertLinkToActionButton.

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants