Skip to content

perf(discovery): reduce per-file allocations in discovery phase#9991

Open
qoole wants to merge 2 commits into
nextcloud:masterfrom
qoole:perf/discovery-allocations
Open

perf(discovery): reduce per-file allocations in discovery phase#9991
qoole wants to merge 2 commits into
nextcloud:masterfrom
qoole:perf/discovery-allocations

Conversation

@qoole
Copy link
Copy Markdown
Contributor

@qoole qoole commented May 7, 2026

Summary

Three micro-optimizations to the discovery hot path that fire once per file/directory in a sync. With large folder trees these allocations add up to noticeable GC and heap churn.

Changes

  • Filename parsing: QString::split('.') allocates a QList<QString> plus copies for each segment, just to recover the basename and extension. Replaced with indexOf / lastIndexOf to find the cut points directly.
  • Zero-copy slices: the basename and extension are then taken as QStringView slices into the original QString rather than allocating new owned QString copies. The downstream forbidden-filename / forbidden-basename / forbidden-extension comparisons all compare against QStringView-compatible data, so no copies are needed.
  • Deferred invocation: five QTimer::singleShot(0, ...) call sites in discovery were replaced with QMetaObject::invokeMethod(Qt::QueuedConnection). Both schedule a slot for the next event loop iteration, but the latter does not allocate a QTimer object on the heap. In a large sync with many directories this eliminates thousands of QTimer allocations.

Behavior is unchanged — same parsing results, same scheduling semantics.

Checklist

AI (if applicable)

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

@qoole qoole force-pushed the perf/discovery-allocations branch from d94f294 to e1cbaca Compare May 7, 2026 18:00
@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.)

Copy link
Copy Markdown
Collaborator

@mgallien mgallien left a comment

Choose a reason for hiding this comment

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

there are two types of changes in your PR
can you split them into separate commits with proper commit messages ?
they might even makes sense to be split into different PRs

qoole added 2 commits May 26, 2026 20:21
…g jobs

Replace the 5 QTimer::singleShot(0, ...) calls that defer
DiscoveryPhase::scheduleMoreJobs with
QMetaObject::invokeMethod(Qt::QueuedConnection). Both achieve the same
deferred (queued) invocation, but invokeMethod does not allocate a
QTimer on the heap for each call. In a large sync with many directories
this eliminates thousands of unnecessary heap allocations.

Signed-off-by: Qoole <2862661+qoole@users.noreply.github.com>
Replace QString::split('.') with indexOf/lastIndexOf to extract the
basename and extension without allocating a QList<QString> per file,
and hold the slices as QStringView so the comparisons against
forbiddenFilenames / forbiddenBasenames / forbiddenExtensions run
against zero-copy views into the original QString instead of allocating
new QString copies.

Signed-off-by: Qoole <2862661+qoole@users.noreply.github.com>
@qoole qoole force-pushed the perf/discovery-allocations branch from e1cbaca to e0b8acf Compare May 26, 2026 19:22
@qoole
Copy link
Copy Markdown
Contributor Author

qoole commented May 26, 2026

Split into two commits as requested:

  • 6341f80 perf(discovery): avoid per-call QTimer heap allocation when scheduling jobs (QTimer::singleShot → QMetaObject::invokeMethod)
  • e0b8acf perf(discovery): use QStringView for forbidden-name checks (QString::split → indexOf/QStringView)

Kept them in this PR for review locality — happy to split into separate PRs if you'd prefer.

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