Skip to content

[stable-34.0] Eliminate O(N²) Realm work in large-folder enumeration - #10469

Merged
i2h3 merged 1 commit into
stable-34.0from
backport/10466/stable-34.0
Jul 28, 2026
Merged

[stable-34.0] Eliminate O(N²) Realm work in large-folder enumeration#10469
i2h3 merged 1 commit into
stable-34.0from
backport/10466/stable-34.0

Conversation

@backportbot

@backportbot backportbot Bot commented Jul 28, 2026

Copy link
Copy Markdown

Backport of PR #10466

…ation

Opening a large remote folder (e.g. /Talk, ~7000 items) for the first time
was pathologically slow: the non-paginated depth-1 write used by change /
working-set enumeration (depth1ReadUpdateItemMetadatas) took ~10 min, and
once the folder was fully cached did not complete within 19 min — ~11
items/sec pinning a single core. The cost was per-item O(N²) work over a
flat folder:

- The logical-address dedup/lookup queries (RealmItemMetadata.hasLocation)
  key on the normalized columns. normalizedServerUrl is indexed but is
  non-selective for a flat folder (every child shares the parent URL), so
  each per-item eviction/lookup scanned all siblings. The selective column,
  normalizedFileName, was not indexed.
- processItemMetadatasToDelete / processItemMetadatasToUpdate diffed the
  existing and incoming sets with in-memory .contains(where:) /
  .first(where:) linear scans — O(existing × updated) — which no index can
  help.

Changes:
- Index normalizedFileName (@persisted(indexed: true)); bump the Realm
  schema to 204 (addedNormalizedFileNameIndexToRealmItemMetadata). The
  index is rebuilt automatically on open; no data migration.
- Rewrite the two set-diff loops to O(N): a Set of incoming ocIds and an
  ocId-keyed dictionary of existing rows replace the linear scans, drop a
  redundant per-item Realm re-open, and cache inheritedKeepDownloaded per
  parent serverUrl. Delete/rename, #9923/#10054 keep-downloaded
  preservation and ticket-96101301 dedup semantics are unchanged.
- Add os_signpost intervals and opt-in wall-clock PERF logging
  (performanceLoggingEnabled user default, off by default) across the
  enumeration path, and gate FileProviderLogger.debug before its Task
  dispatch so disabled debug logging no longer allocates a Task per item.

Measured on production (~6982-item folder): the offending write drops from
635 s / >19 min to ~1.1 s (~6200 items/sec). Full package suite green (325
tests).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: Iva Horn <iva.horn@nextcloud.com>
@backportbot
backportbot Bot requested a review from camilasan as a code owner July 28, 2026 10:45
@backportbot
backportbot Bot requested a review from i2h3 July 28, 2026 10:45
@backportbot backportbot Bot added os: 🍎 macOS Apple macOS, formerly also known as OS X 3. to review feature: 📁 file provider macOS File Provider Extension, more general also known as virtual file system. labels Jul 28, 2026
@backportbot backportbot Bot added this to the 34.0.1 milestone Jul 28, 2026
@github-actions

Copy link
Copy Markdown
Contributor

Artifact containing the AppImage: nextcloud-appimage-pr-10469.zip

Digest: sha256:afad46a08c5dc0fc4de8af39c7477b3ce823a9ad12d1e92db227d38b9fe82507

To test this change/fix you can download the above artifact file, unzip it, and run it.

Please make sure to quit your existing Nextcloud app and backup your data.

@sonarqubecloud

Copy link
Copy Markdown

@i2h3
i2h3 merged commit a500958 into stable-34.0 Jul 28, 2026
21 checks passed
@i2h3
i2h3 deleted the backport/10466/stable-34.0 branch July 28, 2026 12:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

3. to review feature: 📁 file provider macOS File Provider Extension, more general also known as virtual file system. os: 🍎 macOS Apple macOS, formerly also known as OS X

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant