Download Latest Version v1.9.1 source code.tar.gz (200.0 kB)
Email in envelope

Get an email when there's a new version of ThumbmarkJS

Home / v1.9.0
Name Modified Size InfoDownloads / Week
Parent folder
README.md 2026-05-08 3.5 kB
v1.9.0 source code.tar.gz 2026-05-08 199.8 kB
v1.9.0 source code.zip 2026-05-08 231.9 kB
Totals: 3 Items   435.3 kB 1

Highlights

4–5× faster tm.get() on Chromium with byte-identical fingerprint output vs 1.8.1. The win is largest on CPU-constrained devices: mid-tier mobile (Lighthouse 4× throttle) goes from ~210 ms → ~67 ms; low-tier mobile (6×) ~330 ms → ~100 ms.

metric 1.8.1 1.9.0 delta
local total median (Chromium) 117.7 ms 19.6 ms -83%
CPU-throttled 8× total median ~625 ms 136 ms -78%

What changed

  • WebGL: module-scope cache of canvas + GL context + program + buffer (eliminates per-call shader compile + program link); context-loss recovery via webglcontextlost listener with { once: true } semantics; defense-in-depth cache-clear in renderImage's catch block.
  • commonPixels: short-circuit length-1, inline 3-way for length-3 (eliminated 80,000+ allocations per call on the common path).
  • raceAllPerformance: timer cleanup (was leaking 13 setTimeout callbacks per tm.get()).
  • stableStringify: O(1) Set-based cycle detection (replaces O(N) array indexOf).
  • system.getBrowser: memoized (~12 sequential UA regex matches → 1 cached result).
  • audio: removed stray console.error from production hot path.
  • WebRTC: dropped the ICE-candidate wait (with iceServers: [] only host candidates ever fire); fixed an outer-catch resource leak.

New observability (gated on options.performance: true)

The result.elapsed map now also includes:

  • _pipeline.dispatch / _pipeline.resolve / _pipeline.filter / _pipeline.stringify / _pipeline.hash / _pipeline.assembly — per-phase timings inside getThumbmark.
  • _dispatch.<componentName> — per-component sync-prelude timing (the work that runs in the component function before its first await yields).

These have no effect when options.performance is false (the default). They're _-prefixed to signal observability surface — useful for diagnosing perf in the wild. The signature change is what motivated the minor (1.9.0) rather than patch bump.

Hash compatibility

Verified byte-identical fingerprint output vs 1.8.1 on Chromium and Samsung Internet. Two narrow exceptions, both intentional and safe:

  • WebRTC: users whose previous component returned { ..., timeout: true } (the timeout path, fired on slow-network conditions) will see a one-time hash transition to the deterministic { ..., candidateType: 'host' }. These users were already getting non-deterministic fingerprints; they now get a stable one.
  • WebGL caching: cache is OFF for Brave (preserves Brave's per-context noise). Tor / Firefox-RFP typically disable WebGL or return constants — caching gives byte-identical output in those cases.

No breaking changes

The public class (Thumbmark) and free function (getThumbmark) APIs are unchanged.

Cross-browser perf (1.9.0, full mode, 50 iter)

browser local total median
Chromium 24.65 ms
Webkit 10.00 ms
Firefox 227.50 ms

Firefox's slowness is driven by the audio component's OfflineAudioContext setup (~166 ms in dispatch). This is pre-existing, not introduced by this release; it's the next optimization target.

Full report

See docs/perf-optimization-report.md in the repo for the full session methodology, hash-stability discipline, and follow-ups not pursued.

Install

npm install @thumbmarkjs/thumbmarkjs@1.9.0

CDN:

https://cdn.jsdelivr.net/npm/@thumbmarkjs/thumbmarkjs@1.9.0/dist/thumbmark.umd.js
Source: README.md, updated 2026-05-08