Select All + Expand All freezes the UI for ~17-25 s on a large library

32 views
Skip to first unread message

Marie-Jean THORAVAL

unread,
Aug 14, 2026, 12:45:11 PM (5 days ago) Aug 14
to zotero-dev
With a large library, selecting all items and then expanding freezes the whole UI for tens of seconds -- long enough that Windows offers to kill the process.
AI diagnostics below if useful.

Steps to reproduce:
1. A library with many collapsible items (mine: ~18,000 top-level items, ~40,000 rows when expanded).
2. Click into the items list, Ctrl+A.
3. Expand all (or expand the selection with the keyboard).

Timings on 10.0-beta.26+7c52e3013, Windows 11, after a fresh restart with all plugins disabled and auto-sync off, measured with performance.now() around itemsView.expandAllRows() from a script:

    expandAllRows(), nothing selected:   1.1 s  (17,928 -> 40,149 rows)
    selectAll(), then expandAllRows():  17.2 s

The same pair in my normal session (plugins active) is 2.4 s vs ~25 s, so the ratio is stable at roughly 10-15x. The only difference between the two cases is the selection. The per-row expand path (expanding many selected rows via the keyboard) is far worse still, since it pays per-toggle overhead on top -- effectively minutes.

Where the time goes: TreeSelection.adjustForRowInsertion() in chrome/content/zotero/components/virtualized-table.jsx rebuilds the entire `selected` Set on every insertion:

    adjustForRowInsertion(index, count) {
        let selected = new Set();
        for (let selectedIndex of this.selected) {
            selected.add(selectedIndex > index ? selectedIndex + count : selectedIndex);
        }
        this.selected = selected;
        ...

I counted the calls by wrapping adjustForRowInsertion during the frozen expand (the wrapper added ~0.5 s, so the counts describe the real event):

    adjustForRowInsertion calls:      17,882  (one per expanded container)
    selected Set size at every call:  17,928
    total Set operations:        320,588,496  (= 17,882 x 17,928)

So the expand rebuilds a 17,928-entry Set 17,882 times -- about 320 million Set inserts plus 17,882 fresh 18k-entry Set allocations, all on the main thread. (The call sites came in with the recent selection-remapping work -- itemTree.jsx / collectionTree.jsx calling adjustForRowInsertion on row inserts, #5983.)

Debug ID: D2099989934 -- markers "=== [selectall-expand repro]" bracket the baseline and the frozen expand, in a fresh session with all plugins disabled (the only extension active was the debugging bridge used to drive the script, which does not touch the items tree).

Reply all
Reply to author
Forward
0 new messages