Multi-Hoster-Upload/lib
Administrator 121eac5f14 perf(uploads): 1MB read-ahead to absorb read-bursts + instrument the config-persist/load path (v3.3.98)
v3.3.97 (UV_THREADPOOL_SIZE 64→8) was a decisive win — mean event-loop-delay at
70 active uploads dropped 200ms→~11ms (18×), rss 577→287MB, renderer healthy in
14/15 windows. But the user reports it is still not perfectly smooth. A focused
multi-agent investigation plus an adversarial review localized the residual to
TWO distinct, separately-measured spike sources:

1. Read-bursts. In the tail windows the file-read histogram inverts: FSReqCallback
   climbs to 66-70 against threadpool=8 (~8.75× queue depth) while SimpleWriteWrap
   (socket writes) collapses to 4-24 and mean delay rises to 30-42ms. GC is ruled
   out (gcMax ≤27ms in every window). The clean inversion at a stable active=70 /
   pending=1287 shows the reads are causal, not a symptom of a block elsewhere.

2. A suspected synchronous config-persist stall. save() → load() reparses the whole
   electron-config.json — which now carries the 1287-job pending queue nested in
   globalSettings plus full history — on every persist (because _atomicWrite nulls
   the read cache), then _serializeForDisk JSON.stringify(…, null, 2) of all of it.
   One tail sample (max 1021ms, heap spiking to 142MB) fits a large synchronous
   structuredClone+stringify, but it is a single confounded point, so this build
   only INSTRUMENTS the path rather than asserting the cause.

This release ships one behavioral change (kept to a single variable so the next
log attributes cleanly) plus measurement:

- highWaterMark 256KB→1MB in all five streaming read loops (lib/hosters.js,
  doodstream/voe/vidmoly CHUNK_SIZE consts, and the inline value in
  clouddrop-upload.js:108 — NOT the 16MB server chunk at clouddrop-upload.js:12).
  UV_THREADPOOL_SIZE stays 8. This deepens each stream's read-ahead cushion from
  ~0.43s to ~1.7s at the per-stream rate, so a stream tolerates the threadpool
  queue without starving its socket write, and cuts read-completion callbacks and
  per-chunk Buffer allocations ~4×. Byte-correctness is unaffected: Content-Length
  is preamble+fileSize+epilogue, independent of chunk size, and the chunk size
  never touches the multipart boundaries. Fully reversible; a dedicated read-
  concurrency semaphore is held in reserve if 1MB does not clear the bursts.

- config-store.js now times load() (the full reparse, which the account-failed
  handler also hits per failure) and the _commit serialize, logging
  `config-load …` / `config-serialize wall=…ms bytes=… hist=… queue=…` when the
  synchronous work exceeds 20ms. load() is split into a timing wrapper + _loadImpl;
  the timer is a no-op until main.js wires configStore.setPerfLog → logInfo.

The renderer batch-drain fix for the one observed 243ms longtask is intentionally
deferred: that jank is downstream of the main-thread read-burst flooding IPC, so
fix #1 should make it self-heal; bundling it would confound the measurement and
touch the progress hot path. All 397 tests pass.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-21 17:55:34 +02:00
..
account-auth.js fix(doodstream): upload via the doodapi API when an API key exists 2026-05-28 21:42:19 +02:00
account-rotation.js fix(rotation): persist the round-robin cursor so drip-fed uploads keep rotating 2026-06-17 03:33:20 +02:00
backup-crypto.js feat(backup): import legacy password-encrypted backups 2026-04-17 11:22:33 +02:00
clouddrop-upload.js perf(uploads): 1MB read-ahead to absorb read-bursts + instrument the config-persist/load path (v3.3.98) 2026-06-21 17:55:34 +02:00
coalesced-set.js test(coalesce): extract done-removal coalescer + 11 unit tests 2026-04-28 11:59:32 +02:00
config-store.js perf(uploads): 1MB read-ahead to absorb read-bursts + instrument the config-persist/load path (v3.3.98) 2026-06-21 17:55:34 +02:00
diagnostics-agent.js fix(diagnostics): harden read-only agent — grep ReDoS, prototype-chain whitelist bypass, redaction gaps 2026-06-19 18:40:57 +02:00
diagnostics-collectors.js fix(diagnostics): harden read-only agent — grep ReDoS, prototype-chain whitelist bypass, redaction gaps 2026-06-19 18:40:57 +02:00
doodstream-upload.js perf(uploads): 1MB read-ahead to absorb read-bursts + instrument the config-persist/load path (v3.3.98) 2026-06-21 17:55:34 +02:00
file-probe.js fix(rotation): suspect byse rejections now reach every account instead of dying on the first 2026-06-15 01:11:37 +02:00
folder-monitor.js 🐛 fix: folder monitor re-detect deleted files, atomic sync save 2026-03-21 13:31:54 +01:00
hosters.js perf(uploads): 1MB read-ahead to absorb read-bursts + instrument the config-persist/load path (v3.3.98) 2026-06-21 17:55:34 +02:00
ip-allowlist.js feat(diagnostics): network bind + fail-closed IP allowlist + host-in-code (Tailscale, like rd-diagnostics-mcp) 2026-06-19 19:32:29 +02:00
log-mode.js fix(log): persist BARE log path (no compounded daily/session stamps) 2026-06-04 22:08:15 +02:00
log-policy.js feat(log): per-hoster toggle for writing links to fileuploader.log 2026-05-23 15:29:25 +02:00
log-rotation.js test(log): extract log-rotation into testable module + 10 unit tests 2026-04-28 05:10:53 +02:00
orphan-tmp.js fix(queue): close two lost-work / sticky-ghost edge cases found by intensive testing 2026-06-19 06:51:48 +02:00
queue-dedup.js fix(queue): close two lost-work / sticky-ghost edge cases found by intensive testing 2026-06-19 06:51:48 +02:00
queue-prune.js test(queue): extract terminal-job prune into testable module + 10 tests 2026-04-28 06:41:47 +02:00
remote-capture-preload.js debug: add IPC logging from capture window to main process 2026-03-12 08:46:18 +01:00
remote-capture.html fix: native resolution capture + correct click offset for title bar 2026-03-12 08:55:46 +01:00
remote-server.js fix(remote-server): cap WS maxPayload (256 KiB) + guard sendToClient — close a pre-auth parse freeze-sink and a send-throw crash 2026-06-21 03:06:08 +02:00
secret-store.js fix: encrypt hoster credentials at rest; history CSV Link column urls-only 2026-04-19 11:53:59 +02:00
semaphore.js test: add unit tests (41) and UI smoke tests (21), fix semaphore listener leak 2026-03-10 10:55:50 +01:00
stats.js feat(ui): per-hoster success rate, session-paused badge, post-batch retry, link export formats 2026-06-07 20:32:35 +02:00
support-bundle.js fix(diagnostics): harden read-only agent — grep ReDoS, prototype-chain whitelist bypass, redaction gaps 2026-06-19 18:40:57 +02:00
throttle-timer.js fix(queue): completed files no longer reappear in the queue after restart 2026-06-19 04:35:27 +02:00
throttle.js fix: multiple bugs found in deep code analysis 2026-03-11 04:16:50 +01:00
throttled-cache.js test(sort): extract throttled-cache utility + 12 unit tests 2026-04-28 07:12:52 +02:00
updater.js fix(update): cancel active uploads before downloading + add download stall-timeout 2026-06-21 16:33:20 +02:00
upload-log.js fix(queue): stop finished uploads from re-appearing as pending ghosts across restart 2026-06-19 14:53:04 +02:00
upload-manager.js feat(diag): comprehensive high-concurrency measurement build 2026-06-21 16:23:43 +02:00
vidmoly-upload.js perf(uploads): 1MB read-ahead to absorb read-bursts + instrument the config-persist/load path (v3.3.98) 2026-06-21 17:55:34 +02:00
voe-upload.js perf(uploads): 1MB read-ahead to absorb read-bursts + instrument the config-persist/load path (v3.3.98) 2026-06-21 17:55:34 +02:00
webhook-notify.js fix(webhook): retry+429+status handling, await before shutdown, error-path notify, abort/auto-retry suppress, Discord limits 2026-06-10 00:08:02 +02:00