# The First Call Is a Lie

*Task 1 of 4 · [Measuring Speed Honestly](https://gpu.rocks/learn/measuring-speed-honestly-b9188894.md) · GPU.js Learn*

The first time you invoke a kernel, gpu.js does far more than run it: it
**transpiles** your JavaScript function to shader code, hands it to the GPU
driver to **compile and link**, allocates buffers — and *then* runs it.
In `auto` mode there is more still: that first call is also where gpu.js asks the
browser for a WebGPU adapter and rebuilds your kernel for it, so the backend swap happens
inside the first `await` too. Every call after it skips straight to the run.

So timing the first call measures the compiler, not your kernel. How wide the gap looks
depends on the backend and on what the driver has already cached: on this page the first
call typically costs a few times a warm one on WebGPU and ten times or more on WebGL, and on
a big kernel with a cold shader cache it is wider still. What never changes is that it
happens exactly once — which is why every honest benchmark **warms up first**
and throws that first measurement away.

## Figures

- **the first call buys the compiler — time the calls after it**

## Goal

**Goal:** finish the kernel, then use `Date.now()` to time the
*first* call and the *warmed-up* average separately — and log both.

## Requirements

- Finish the kernel: return `Math.sin(x / 100) * 100` where `x` is this thread's index
- Time the first call with `Date.now()` and log it: `first call: N ms`
- Await 10 more calls in one timed block and log the average: `warm call: N ms`

## Hint 1 — the stopwatch pattern

Snapshot the clock, do the work, subtract:

```js
const t0 = Date.now();
// … the work …
console.log('first call:', Date.now() - t0, 'ms');
```

## Hint 2 — averaging the warm calls

One stopwatch around a loop of 10 calls, then divide:

```js
t0 = Date.now();
for (let i = 0; i < 10; i++) await wave();
console.log('warm call:', (Date.now() - t0) / 10, 'ms');
```

## Same idea elsewhere

Every platform has a version of this pause: CUDA JIT-compiles PTX at first launch
(then caches it), WebGPU builds the shader in `createComputePipeline`, Metal
compiles MSL when the pipeline state is created. Benchmarking guides on all of them open
with the same rule — discard the first iteration.

## Starter code

```js
// The first call compiles. The rest just run. Prove it.
const gpu = new GPU({ mode });

const wave = gpu.createKernel(function () {
  // TODO: return Math.sin(x / 100) * 100, where x is this thread's index
  return 0;
}, { output: [2048] });

// TODO: time the FIRST call with Date.now():
//   const t0 = Date.now();  ...await wave()...
//   console.log('first call:', Date.now() - t0, 'ms');
const result = await wave();

// TODO: await wave() 10 more times inside one timed block, then log the
// average as:  console.log('warm call:', totalMs / 10, 'ms');

console.log('sample value:', result[100]);
```

---

Interactive version: https://gpu.rocks/learn/measuring-speed-honestly-b9188894/1

[Next task](https://gpu.rocks/learn/measuring-speed-honestly-b9188894/2.md)
