v145 · Web APIs · Bimodal Demo

Bimodal Demo

Collects resource timing data for repeated fetches, uses transferSize to split cache hits from network fetches, and shows separate statistics for each population.

This demo fetches the page stylesheet multiple times. The first fetch is a network request; subsequent fetches come from the browser cache. Resource Timing's transferSize field reveals which population each measurement belongs to, exposing the bimodal distribution.

distribution

Click “Run demo” to collect data.

Fetches collected
Fast (cached) — count
Fast — p50 duration
Fast — p95 duration
Slow (network) — count
Slow — p50 duration
Overall mean (misleading)

code

function percentile(sorted, p) {
  if (!sorted.length) return NaN;
  const i = Math.floor(p * (sorted.length - 1));
  return sorted[i];
}

async function collectTimings(url, n = 20) {
  // Clear buffered entries
  performance.clearResourceTimings();

  for (let i = 0; i < n; i++) {
    // cache: 'no-store' for first, default for rest to allow caching
    await fetch(url, { cache: i === 0 ? 'no-store' : 'default' });
  }

  const entries = performance.getEntriesByName(url);
  const fast = [], slow = [];

  for (const e of entries) {
    // transferSize=0 + encodedBodySize>0 → cache hit
    if (e.transferSize === 0 && e.encodedBodySize > 0) {
      fast.push(e.duration);
    } else {
      slow.push(e.duration);
    }
  }

  fast.sort((a, b) => a - b);
  slow.sort((a, b) => a - b);

  return { fast, slow };
}

see also