# Glass-to-glass latency, measured from outside

This is the instrument behind the published numbers, not a description of it.
The files are copied verbatim from the repository that ran the campaigns, and
`sha256sums.txt` is recorded in every run record, so what you download can be
checked against what was measured.

## What it measures

A probe inside the streamed desktop draws a 12-bit timecode of
`CLOCK_MONOTONIC` milliseconds, redrawn at 240 Hz. An observer on the client
machine reads that timecode out of the client's window and subtracts its own
clock.

**Included:** the probe's draw and commit, the streamed desktop's compose, the
capture, the hardware encode, transport and pacing, the jitter buffer, the
hardware decode, and the client's present into its framebuffer.

**Excluded:** the client monitor's scanout -- so this is
glass-to-*framebuffer* -- and any input path. Nothing here measures how long a
keystroke takes to come back.

## Why it can be trusted across the boundary

The two clocks have to be one clock. A container shares its host kernel's
`CLOCK_MONOTONIC` unless a time namespace says otherwise, and `clock_gate.py`
asserts that per run rather than assuming it: `/proc/1/timens_offsets` is the
authority, while comparing the inode of `/proc/1/ns/time` produces false
negatives on perfectly healthy containers.

Across two physical machines this does not hold, and this instrument does not
apply. Measure a VM or a container from its host.

## Running it

    make                                   # builds g2g_probe (needs libX11)
    # copy g2g_probe into the streamed desktop and run it there:
    #   DISPLAY=:0 ./g2g_probe --hz 240 [--motion]
    ./run.py --window <client window name> [--container <name>]

`--motion` adds a deterministic full-screen damage field: the "full motion"
workload in the published tables. Without it the desktop is still and only the
timecode changes.

## The validity gate

A measurement is reported as INVALID rather than as a number when fewer than
80% of samples land in `0 < x < 1000 ms`, when fewer than half are distinct
from their predecessor (a frozen stream reports plausible 400-700 ms
"latencies"), or when the observer's own median grab cost exceeds 5 ms, which
means the instrument has become part of what it measures.

## What it will not tell you

Latency between two machines, input-to-photon time, or anything trustworthy
about a stack whose client window is covered: the observer reads the root
framebuffer at the window's coordinates, so an editor sitting on top of the
viewer is what gets measured. It fails loudly when the timecode is missing and
quietly when it is merely half-covered, which is why the published campaigns
record the strip's width per session and reject any cell that reads narrower
than the first one did.
