Skip to content

Local engineering spec. Investigated and reverted on 2026-06-11 — kept as a durable finding. GeoLocation is display-only (no eD2K/Kad protocol surface).

REF-057 - Defer GeoLocation MMDB load off the pre-window startup path

Problem (original hypothesis)

Diagnostics-build startup profiling against a real, heavy profile (known.met ~40 MB, 40,558 shared files) showed Construct CGeoLocation costing ~3.5 s on a cold OS file cache (~0 warm). It runs synchronously in InitInstance (Emule.cpp geolocation->Load()) before the main window exists, so the hypothesis was that deferring it off the pre-window path would cut cold startup.

What was tried

  1. Cache-warm worker + post-window UI-thread Load().
  2. Build-on-worker + adopt-pointer-on-UI (UM_GEOLOCATION_INITIAL_LOADED), keeping the m_pDatabase swap UI-thread-only.

Both built clean across Debug|x64, Release|x64, and Release|x64 diagnostics.

Why it was reverted (evidence)

Re-profiling (cold + warm ×3 per variant) showed the change is not worth it:

  • Construct CGeoLocation correctly dropped to ~0, but cold startup.complete moved only ~24.9 s → ~24.3 s — within the run-to-run variance of the dominant loads (known.met cold read alone swung 10.1/10.1/11.2 s across runs).
  • Cold startup is disk-I/O-bound throughout (40 MB known.met + shared scan + part files). Parallelizing the geo read does not hide it — the worker's 3.5 s cold read then contends on disk with the finalize-stage I/O (downloadqueue->Init, etc.), eating most of the nominal savings.
  • Warm startup saw no benefit (geo is ~0 warm).
  • Net: a marginal, noise-masked, cold-only win bought with a cross-thread DB pointer hand-off — the precise concurrency class to avoid for low payoff.

Evidence: EMULEBB_WORKSPACE_OUTPUT_ROOT\reports\startup-profile\ runs 20260611T090338Z (baseline), 20260611T0941Z-geodefer, 20260611T0953Z-geoadopt.

Durable takeaway

The real startup cost is structural and disk-bound: CKnownFileList (known.met/cancelled.met) ~7.8 s warm / ~10 s cold and CSharedFileList scan/bind ~6 s, both serialized on the UI thread. The win is to read/parse less or defer the data-model population (async known/shared load with an explicit "loading" state), not to parallelize a single small read against an already disk-saturated startup. That is deeper, concurrency-sensitive, protocol-adjacent 0.8.x structural work.

Disposition

Deferred to 0.8.x. Revisit only as part of the broader known/shared async-load effort, where geolocation could ride the same off-thread-load + adopt machinery.