show press-to-paint in the panel, temporarily
The lag is felt in the browser and every number so far was measured somewhere else. At x11vnc's own socket, press-to-paint is ~50ms: median 47ms over 8 synthetic presses, and 51ms with a second x11vnc running with X DAMAGE enabled — so -noxdamage costs nothing and the comment defending it stands. What that cannot include is the sidecar relay, the platform's socket relay and the network, which is where the rest of the lag has to be. This prints the end-to-end figure in the status row so the two can be subtracted. Instrumentation, not a feature. Delete it and its row once the question is settled. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Officer-Session: f7a62308-0977-4cf4-aa29-c020853fd420
This commit is contained in:
@@ -82,6 +82,19 @@ export const MinesweeperPanel = () => {
|
|||||||
const [frame, setFrame] = useState<{ width: number; height: number } | null>(null);
|
const [frame, setFrame] = useState<{ width: number; height: number } | null>(null);
|
||||||
const [box, setBox] = useState<{ width: number; height: number; dpr: number; zoom: number } | null>(null);
|
const [box, setBox] = useState<{ width: number; height: number; dpr: number; zoom: number } | null>(null);
|
||||||
const [status, setStatus] = useState<SessionStatus | null>(null);
|
const [status, setStatus] = useState<SessionStatus | null>(null);
|
||||||
|
/*
|
||||||
|
TEMPORARY INSTRUMENTATION — press-to-paint, measured where it is actually felt.
|
||||||
|
|
||||||
|
The same figure taken at x11vnc's own socket is ~50ms (median 47ms over 8 synthetic presses, and 51ms
|
||||||
|
with the X DAMAGE extension enabled, so `-noxdamage` is not costing anything). What that number cannot
|
||||||
|
include is the two relay hops and the network, and those are the only places the rest of the lag can
|
||||||
|
be. This is the end-to-end figure, so the two can be subtracted.
|
||||||
|
|
||||||
|
Cleared on the frame that follows a press, so it times the first paint after a click rather than every
|
||||||
|
repaint. Delete this and its row below once the question is settled.
|
||||||
|
*/
|
||||||
|
const pressAtRef = useRef<number | null>(null);
|
||||||
|
const [lagMs, setLagMs] = useState<number | null>(null);
|
||||||
const [error, setError] = useState<string | null>(null);
|
const [error, setError] = useState<string | null>(null);
|
||||||
const [connected, setConnected] = useState(false);
|
const [connected, setConnected] = useState(false);
|
||||||
const [busy, setBusy] = useState(false);
|
const [busy, setBusy] = useState(false);
|
||||||
@@ -200,6 +213,10 @@ export const MinesweeperPanel = () => {
|
|||||||
},
|
},
|
||||||
onFrame: (image, x, y) => {
|
onFrame: (image, x, y) => {
|
||||||
canvasRef.current?.getContext('2d')?.putImageData(image, x, y);
|
canvasRef.current?.getContext('2d')?.putImageData(image, x, y);
|
||||||
|
if (pressAtRef.current !== null) {
|
||||||
|
setLagMs(Math.round(performance.now() - pressAtRef.current));
|
||||||
|
pressAtRef.current = null;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
onCopyRect: (from, to) => {
|
onCopyRect: (from, to) => {
|
||||||
// Same canvas as source and destination, which is what CopyRect is: the 2D context takes a
|
// Same canvas as source and destination, which is what CopyRect is: the 2D context takes a
|
||||||
@@ -301,7 +318,10 @@ export const MinesweeperPanel = () => {
|
|||||||
const rfb = rfbRef.current;
|
const rfb = rfbRef.current;
|
||||||
if (!rfb) return;
|
if (!rfb) return;
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
if (kind === 'down') ev.currentTarget.focus();
|
if (kind === 'down') {
|
||||||
|
ev.currentTarget.focus();
|
||||||
|
pressAtRef.current = performance.now();
|
||||||
|
}
|
||||||
|
|
||||||
if (kind !== 'move') {
|
if (kind !== 'move') {
|
||||||
const bit = BUTTON_MASK[ev.button] ?? 0;
|
const bit = BUTTON_MASK[ev.button] ?? 0;
|
||||||
@@ -351,6 +371,10 @@ export const MinesweeperPanel = () => {
|
|||||||
game or a repair for when it stops behaving, and a footer is where neither gets read. */}
|
game or a repair for when it stops behaving, and a footer is where neither gets read. */}
|
||||||
<div className="flex shrink-0 items-center gap-4 text-sm text-primary">
|
<div className="flex shrink-0 items-center gap-4 text-sm text-primary">
|
||||||
<span>{connected ? 'connected' : 'connecting…'}</span>
|
<span>{connected ? 'connected' : 'connecting…'}</span>
|
||||||
|
{/* Temporary — see `pressAtRef`. ~50ms of this is the game and the capture; the rest is the trip. */}
|
||||||
|
<span title="Press to painted pixels, measured in this browser. Source-side is ~50ms of it.">
|
||||||
|
lag {lagMs === null ? '—' : `${lagMs}ms`}
|
||||||
|
</span>
|
||||||
{/* Focus decides where keys go, and a canvas gives no hint that it can hold any. */}
|
{/* Focus decides where keys go, and a canvas gives no hint that it can hold any. */}
|
||||||
<span>click the board to send it keys</span>
|
<span>click the board to send it keys</span>
|
||||||
<button type="button" onClick={() => void refresh()} className="flex items-center gap-1.5 hover:underline">
|
<button type="button" onClick={() => void refresh()} className="flex items-center gap-1.5 hover:underline">
|
||||||
|
|||||||
Reference in New Issue
Block a user