I think the Airscape log confirms my theory. Part of it has a dt sequence with these measurements:
31ms, 25ms, 41ms, 20ms, 31ms, 19ms, 35ms
There is variation from 19ms to 41ms - over double. This is really uneven frame scheduling and probably explains why it looks so bad, it's a totally unpredictable framerate frequency. I would expect frame-by-frame the actual CPU/GPU workloads are almost identical, unless you have significantly intensive events coded to run every other frame or every N frames. Assuming even workloads for each frame, this is probably bad scheduling by the browser.
At 37 FPS each frame is probably taking about 27ms to process, while the screen is drawn every 16.7 ms. If I write out how this is being scheduled...
Vsync 1: 16.7ms (skip)
Vsync 2: 33.3ms (render frame 1)
Vsync 3: 50ms (skip)
Vsync 4: 66.7ms (render frame 2)
Vsync 5: 83.3ms (skip)
Vsync 6: 100ms (render frame 3)
Vsync 7: 116.7ms (render frame 4)
Vsync 8: 133.3ms (skip)
Vsync 9: 150ms (render frame 5)
Vsync 10: 166.7ms (render frame 6)
Vsync 11: 183.3ms (skip)
Vsync 12: 200ms (skip)
Vsync 13: 216.7ms (render frame 7)
See how it's alternating between rendering two adjacent frames 16ms apart (e.g. render frames 3 + 4) and skipping two adjacent frames (e.g. render frames 6 and 7, which end up falling about 50ms apart!). No wonder it looks bad, that's like switching between 60 FPS and 20 FPS every few frames.
This needs to be solved on the browser side, I think. It looks like when each frame takes longer than a Vsync period to process then it starts aliasing really badly against the refresh rate. The only sensible alternative is to have the browser drop it right down to 30 FPS, which is a lower rate but at least looks predictable. I'll see if I can make a demo and file a bug report for Chrome...