Files
Kigi-CLI/crates/codegen/kigi-pager-pty-harness/src/timing.rs
T
ZacharyZhang-NY a02b555e66 docs(comments): rewrite comments across all crates to the guidelines
Sweep every first-party crate source (1956 .rs files) to the project comment
guidelines: delete redundant restatements, decorative banners, change
narration, and end-of-line comments; keep and tighten the crucial ones
(invariants, bug rationale, SAFETY blocks, ported-source attribution).

No functional code changed. Every edit is proven comment-only against the
prior tree by a comment-stripping lexer (string/char/raw-string aware) plus a
separate doctest-fence check. Where removing a comment made rustfmt or clippy
want to re-lay-out adjacent code, the minimal triggering comment is restored so
code tokens stay byte-identical.

Gates green: cargo fmt --all --check (0 diffs), cargo check and cargo clippy
--workspace --all-targets (0 warnings).

Adds scripts/check_codegen_comment_guidelines.py — the enforcement gate for
these guidelines (flags banners, end-of-line comments, change narration, and
commented-out code).
2026-07-23 16:55:39 -04:00

119 lines
3.1 KiB
Rust

//! Layer 2b: Frame timing via VTE parser.
//!
//! Detects frame boundaries from synchronized-update markers
//! (`CSI ? 2026 h/l`) emitted by crossterm's `BeginSynchronizedUpdate` /
//! `EndSynchronizedUpdate`, and records wall-clock timing for each frame.
use std::time::{Duration, Instant};
// `vte` is re-exported by `alacritty_terminal` (pulled in via ptyctl), so no
// direct dependency on it is needed.
use alacritty_terminal::vte;
#[derive(Debug, Clone)]
pub struct FrameTiming {
/// Wall-clock duration from BeginSynchronizedUpdate to EndSynchronizedUpdate.
pub duration: Duration,
/// Number of printable characters emitted within this frame.
pub chars: usize,
}
pub struct FrameTimingParser {
vte_parser: vte::Parser,
handler: FrameTimingHandler,
}
impl FrameTimingParser {
pub fn new() -> Self {
Self {
vte_parser: vte::Parser::new(),
handler: FrameTimingHandler::new(),
}
}
pub fn feed(&mut self, bytes: &[u8]) {
self.vte_parser.advance(&mut self.handler, bytes);
}
pub fn timings(&self) -> &[FrameTiming] {
&self.handler.timings
}
/// Counts only frames whose end marker has been seen; a frame still open
/// is not included.
pub fn frame_count(&self) -> u64 {
self.handler.timings.len() as u64
}
pub fn reset(&mut self) {
self.handler.timings.clear();
self.handler.frame_start = None;
self.handler.current_frame_chars = 0;
}
}
impl Default for FrameTimingParser {
fn default() -> Self {
Self::new()
}
}
struct FrameTimingHandler {
frame_start: Option<Instant>,
timings: Vec<FrameTiming>,
current_frame_chars: usize,
}
impl FrameTimingHandler {
fn new() -> Self {
Self {
frame_start: None,
timings: Vec::new(),
current_frame_chars: 0,
}
}
}
impl vte::Perform for FrameTimingHandler {
fn csi_dispatch(
&mut self,
params: &vte::Params,
intermediates: &[u8],
_ignore: bool,
action: char,
) {
// Synchronized-update markers are private modes, so anything without
// the `?` intermediate cannot be one.
if intermediates != b"?" {
return;
}
let param_val: u16 = params
.iter()
.next()
.and_then(|p| p.first().copied())
.unwrap_or(0);
if param_val == 2026 {
match action {
'h' => {
self.frame_start = Some(Instant::now());
self.current_frame_chars = 0;
}
'l' => {
if let Some(start) = self.frame_start.take() {
self.timings.push(FrameTiming {
duration: start.elapsed(),
chars: self.current_frame_chars,
});
}
}
_ => {}
}
}
}
fn print(&mut self, _c: char) {
self.current_frame_chars += 1;
}
}