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