Skip to content

fix: classify device capabilities by platform#12454

Open
huhuanming wants to merge 9 commits into
xfrom
codex/fix-device-performance-tier
Open

fix: classify device capabilities by platform#12454
huhuanming wants to merge 9 commits into
xfrom
codex/fix-device-performance-tier

Conversation

@huhuanming

@huhuanming huhuanming commented Jul 12, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Classify native CPU capability with static device-to-tier mappings.
  • Classify web and extension concurrency from navigator.hardwareConcurrency.
  • Expose exact desktop logical-processor count and physical memory through the existing synchronous preload bridge, with browser capability fallbacks.
  • Cache the Electron main-process platform snapshot and cache capability profiles per JS runtime/context so repeated consumers do not repeat OS, native-backed, or storage reads.
  • Expose CPU and memory as independent capabilities and resolve Tab preloading through a feature-specific policy.
  • Write one sanitized local diagnostic entry for the resolved capability and Tab preload decision.

Intent & Context

Previous classification mixed RAM and startup timing with CPU capability. It also relied on human-readable iOS marketing names, which can change when the device library updates.

This change makes device capability inputs deterministic, keeps memory independent from CPU, and lets each feature combine only the signals relevant to its workload.

Root Cause

  • RAM is not a reliable CPU-performance proxy.
  • Startup time is an application outcome rather than a stable hardware capability.
  • Human-readable iOS model names are less stable than hardware model identifiers.
  • A global effective tier coupled CPU, memory, and downstream feature behavior.
  • Browser targets had no stable non-native capability source after native classification was separated.

Design Decisions

  • Store only low, medium, and high tier labels in bundled native catalogs; no benchmark scores or source-data processing code is included.
  • Use exact modelId -> tier lookup on iOS and do not read the user-editable device name or marketing model name.
  • Use manufacturer -> model -> tier grouped lookup on Android to avoid repeated manufacturer strings and composite-key allocation.
  • Normalize Android manufacturer/model only for case and whitespace; do not use fuzzy punctuation matching.
  • Validate Android own properties and tier values so custom build properties cannot traverse object prototypes.
  • Represent CPU and memory as independent capability objects.
  • Classify non-native concurrency as low for 1–4 logical processors, medium for 5–7, and high for 8 or more.
  • Treat browser hardwareConcurrency as a medium-confidence concurrency proxy, not a CPU benchmark; browsers may reduce the value for privacy.
  • Use exact OS logical-processor count and physical memory on desktop through the existing synchronous preload bridge.
  • Build the desktop platform payload lazily once in Electron main and reuse it for every renderer preload request. Each renderer still performs its required bootstrap IPC once and receives a structured-cloned value.
  • Cache the resolved capability profile in each JS runtime/context. Native main and bg heaps are independent; each runtime resolves once if it imports the module.
  • Use approximate navigator.deviceMemory on web/extension when available; keep unknown values unknown.
  • Default an unmapped or unavailable CPU signal to unknown; each feature policy chooses its own fallback.
  • Cap mobile Web and short-lived extension popup surfaces at light Tab preloading even when CPU concurrency is high.
  • Keep DApp WebView retention RAM-only and GPU behavior capability/fallback based.
  • Retain the legacy performance-tier API only as a deprecated compatibility surface.
  • Do not calibrate any platform from UI-visible/startup timing.
  • Log only tier/source/confidence, memory class, policy mode/reason, and data version to the local logger once per UI/main JS runtime. Device names, model identifiers, exact memory, and user identifiers are excluded, and the event is not sent to analytics or a server.

Changes Detail

  • Add platform-specific native CPU-tier lookup and static tier catalogs.
  • Add stable iOS model-ID lookup and regression coverage for iPhone and iPad identifiers.
  • Group Android models by manufacturer and add prototype-path rejection coverage.
  • Add logical-processor classification for web and extension.
  • Add desktop-specific capability readers backed by synchronous preload bridge fields.
  • Add a lazy process-lifetime cache for the Electron main-process platform payload.
  • Add per-JS-runtime/context capability profile caches with repeated-read regression coverage.
  • Add independent CPU and memory capability types and resolution for all targets.
  • Add a feature-specific Tab preload policy with explicit mode and reason.
  • Reuse memory classification for DApp WebView retention.
  • Remove startup-time calibration from Tab Navigator.
  • Add a deduplicated local diagnostic entry when the Tab preload policy is resolved.
  • Add regression, capability-independence, policy, logging, desktop bridge, fallback, cache, and catalog privacy tests.

Risk Assessment

  • Risk Level: Medium
  • Affected Platforms: iOS, Android, Web, Desktop, and Browser Extension
  • Risk Areas: Native catalog freshness, browser privacy-reduced capability values, and conservative behavior for unknown devices.
  • Runtime scope:
    • Native Tab consumers and diagnostics run in the main JS runtime. The native bg runtime initializes independently and does not import the catalog or UI policy in this flow.
    • Native capability profiles are per-runtime JS objects. main and bg do not share the cached object or deserialized data; if both import it, each resolves independently once. Native constants/storage are backed by native resources, but no JS readiness or object sharing is assumed across runtimes.
    • Web, desktop, and extension Tab consumers run in the UI/main runtime. Extension background/service-worker runtimes initialize independently and do not participate in the Tab decision.
    • Desktop OS capability primitives are read once into an Electron main-process JS snapshot and copied synchronously into each renderer through preload. Renderers keep independent deserialized primitive copies; no live OS/native handle is shared with a renderer profile.
    • Native main-JS and bg-JS bundles remain version-locked; practical version skew is native-vs-JS, not bg-vs-main.

Test plan

  • Targeted CPU-tier, memory capability, Tab policy, local logging, desktop bridge, fallback, cache, and catalog privacy tests (11 suites / 53 tests)
  • Verify repeated Desktop renderer requests reuse one Electron main-process platform snapshot
  • Verify repeated Native/Web/Desktop/Extension profile reads access capability and storage inputs once per JS runtime/context
  • Verify iOS model identifiers resolve without marketing-name normalization
  • Verify Android manufacturer/model normalization and grouped lookup
  • Verify Android prototype-property paths are rejected
  • Verify browser logical-processor thresholds and unknown fallbacks
  • Verify desktop bridge values take precedence and browser values remain a fallback
  • Verify the diagnostic entry is local-only, sanitized, and emitted once per UI/main JS runtime
  • Verify high CPU plus constrained memory keeps CPU high while disabling only Tab preloading
  • Root TypeScript check
  • yarn agent:check --profile commit
  • Extension MV3 production rspack compilation
  • Web production rspack compilation
  • Desktop main/preload and renderer production compilation
  • Verify the capability profile and Tab policy on physical iOS and Android devices from Developer Settings
  • Verify the capability profile and selected Tab policy in desktop, web, extension popup, and extension standalone UI

@huhuanming
huhuanming force-pushed the codex/fix-device-performance-tier branch from 8606330 to 3c65344 Compare July 12, 2026 13:33
@huhuanming huhuanming changed the title fix: classify native device performance by benchmark fix: classify native device capabilities by tier Jul 12, 2026
@huhuanming
huhuanming force-pushed the codex/fix-device-performance-tier branch from 8a76c11 to b585a2c Compare July 12, 2026 15:10
@huhuanming
huhuanming force-pushed the codex/fix-device-performance-tier branch from b585a2c to 3558335 Compare July 12, 2026 15:26
@huhuanming huhuanming changed the title fix: classify native device capabilities by tier fix: classify device capabilities by platform Jul 13, 2026
@huhuanming
huhuanming marked this pull request as ready for review July 13, 2026 14:37
@huhuanming
huhuanming enabled auto-merge (squash) July 13, 2026 14:37
Comment thread packages/kit/src/routes/Tab/preloadPolicyResolver.ts
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants