Skip to content

v0.4.6

Choose a tag to compare

@corvofiox corvofiox released this 22 Oct 21:01
· 9 commits to main since this release

Com Bridge v0.4.6

两处输入热路径修复 + 一套可量化的延迟诊断。

修:副机某块屏上鼠标"非常迟滞、手停了光标还在追"

现象(用户实测):副机 2560×1600 屏上移动非常迟滞,同样操作在 1920×1080 屏上正常。

原因在事件流本身,与屏幕像素无关:

  1. 输入是 UDP,消费端一时跟不上,事件就堆在内核接收缓冲里
    (默认 64KB ≈ 3400 条 19 字节事件 ≈ 3 秒的量);
  2. 旧实现逐条取出、逐条注入,每条都要付一次 SendInput 的代价,
    于是积压只能按"消费速率"慢慢排空 —— 主观上就是光标在追手。
    副机的光标从进入边(在 2560 屏上)开始就一直背着这段积压跑,
    等到 1920 屏时已经排空,所以"只有那块屏迟滞"。

修复(transport.coalesce_moves):收到一条事件后先看 socket 里还有没有积压,
有就继续攒,再把相邻位移合并成一条注入。

  • 光标只需要最终位置:k 条相邻位移等价于 1 条 (Σdx, Σdy),落点不变;
  • 合并后一轮只付一次 SendInput,积压立刻塌到最新位置,不再"追手";
  • 只合并相邻的移动事件,绝不跨越按键/滚轮 —— [移动, 点击, 移动]
    的顺序即语义,压掉点击就会点错位置;
  • 没有积压时行为与旧版完全一致(逐条交付),不平白引入延迟。

实测数字(副机 0.4.6,diag_lat 每 5 秒一行,用户在两块屏间正常移动):

接收=797/s  批=3849  最大积压=39  合并=1821  注入均=1.01ms 峰=15.8ms | 光标=(0,636) 屏=2560x1600@0,0

关键在 注入均=1.01ms:SendInput 一次就要约 1ms,而主机上报率约 800~1000 事件/秒
—— 旧实现"每条一注入"正好把消费端顶在 100% 饱和,任何一次系统抖动(峰值 15.8ms)
都会让它落后,落后就只能靠后续慢慢排空,于是"手停了光标还在追"。
合并后一次注入覆盖整批,消费端从饱和降到约一半,两块屏都跟手。

修:主机接多块屏时,越界边落在错误的边缘

主机侧越界判定一直用"面积最大的那块屏",而副机侧用的是整个虚拟桌面。
两块屏并排时,那条边正好在桌面中间 —— 光标走到中间就判"越界",把输入送去副机。

现在两侧统一用 virtual_desktop();多屏时启动日志会打印实际基准与屏数。

新增:管线延迟诊断(默认关闭)

%LOCALAPPDATA%\ComBridge\diag_lat.flag(或环境变量 COM_BRIDGE_DIAG_LAT=1)
存在时,副机每 5 秒打印一行:

[agent][lat] 接收=812/s 交付=794/s 批=… 最大积压=… 合并=… 注入均=0.42ms 峰=3.1ms | 光标=(x,y) 屏=2560x1600@0,0 | hider 隐藏=0.0/s 收起=0.0/s

判读:

观察 结论
接收 远低于主机上报率,最大积压 恒为 1 事件在路上就丢了,不是本地慢
最大积压 持续 > 1、合并 持续增长 确实在排队;本次合并已把积压塌缩成一次注入
注入均/峰 本身是毫秒级 SendInput 在这块屏/这台机器上就慢(系统/驱动层面)
hider 隐藏/收起次数快速上涨 隐藏器在反复抢前台,与鼠标事件量无关

其他

  • 输入事件时间戳改用 perf_counter 微秒时钟(time.monotonic_ns() 在 Windows
    上分辨率只有 15ms,无法用来量化延迟)。
  • 新增 15 项回归测试(tests/test_input_batching.py):位移总量守恒、
    非移动事件不被合并且顺序不变、无积压时逐条交付、真 UDP 突发往返。