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

…ot path

- ActivityListModel::data: cache FolderMan::instance() once per role
  evaluation instead of dereferencing the singleton twice for every
  row that has a file path. The Roles::PathRole and getDisplayPath
  lambda each used to call FolderMan::instance() twice; now once.
- ActivityListModel::convertLinkToActionButton: move the reply icon
  URL construction inside the isReplyIconApplicable branch, and bake
  the trailing slash into the QStringLiteral so the path is a single
  immutable literal instead of two QString::operator+ allocations
  per activity link.
- User::slotRefresh: cache _account.data() once and reuse instead of
  calling .data() five times in a row. Slight readability improvement
  alongside the avoided refcount manipulations.

Signed-off-by: Qoole <2862661+qoole@users.noreply.github.com>
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

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;

{
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

@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.)

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