Skip to content

v0.11.0

Latest

Choose a tag to compare

@github-actions github-actions released this 06 Aug 14:45
· 1 commit to main since this release
v0.11.0: handle very large tab counts (fixes #1)

Reported: with ~1600 tabs open, the export stalled and eventually crashed.
Reproduced against a real 1613-tab load. Four separate problems, only one of
which was the export.

1. The export made one Apple Event round-trip per property, per tab
   (title/URL/loading inside the tab loop): ~4800 IPC calls at 1600 tabs.
   Measured 53 ms/tab — 11.2 s at 213 tabs, ~85 s at 1613 (still running when
   killed at 31 s). Now uses bulk access, `title of every tab of w`, which is
   one round-trip per property per window. Cost scales with windows, not tabs.
   Applied to both the Chromium and Safari scripts.

2. A timeout silently returned an empty list, so past roughly 380 tabs the app
   reported "No open tabs found in the running browsers" — a failed read was
   indistinguishable from having no tabs. Failures now raise ExportError, which
   the existing dialog surfaces. Gather timeout 20 s -> 60 s; count timeout
   5 s -> 20 s (a browser with 1600 tabs needs 3-4 s just to answer a bulk
   count).

3. The counter was slower than its own poll timer, which is likely what the
   report actually experienced. running_process_names() asked System Events for
   the process list on every poll: 2248 ms measured. Combined with the count,
   count_all() took 4.72 s against a 4 s timer. Now uses NSWorkspace, a local
   API call needing no Automation permission: 44 ms. System Events kept as a
   fallback when PyObjC isn't available.

4. No re-entrancy guard, so slow polls stacked up and piled concurrent
   AppleScript calls on each other. refresh() now skips a tick if one is still
   in flight; the next catches up.

Results at 1613 tabs:
  export gather      ~85 s (timed out, returned nothing)  ->  2.0 s
  full export        failed                               ->  2.8 s
  count_all()        4.72 s (vs a 4 s timer)              ->  1.83 s
  process lookup     2248 ms                              ->  44 ms

A hypothesis that proved wrong, recorded so nobody re-does it: AppleScript's
`outp & ...` string building was assumed to be quadratic. Benchmarked at 1600
concatenations in 0.08 s. The IPC round-trips were the whole story.

Tests: a forced timeout must raise rather than return empty, and the bulk
query's true/false booleans must still map to the yes/no the CSV uses.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>