‹ Term

GPU 渲染性能基准

Term 的终端渲染改用 EGL/GLES3 实例化渲染器 —— 在真机上实测的方法、数据与画面。

5.3ms
GPU 帧时间 · 188 fps
2.7×
对比 CPU 路径
0.2ms
GL 绘制 / 帧
结果

同一台真机(华为 Pura 70)、同一份语料,通过内置的 Log frame stats 开发者开关,将 GPU 路径与 CPU 基线做 A/B 对比。

工作负载 CPU 路径 GPU 路径 提速
全屏滚动(firehose) 14.6 ms · 68 fps 5.3 ms · 188 fps 2.7×
慢速滚动(~5 行/帧) 12.8 ms · 76 fps 6.0 ms · 167 fps 2.1×
logFrameStats · 华为 Pura 70 · 3 MB ANSI-SGR + CJK 语料循环 · 2026-07

GPU 路径的帧时间几乎与滚动量无关 —— 每一帧都是一次完整重绘,而这对 GPU 来说很便宜。CPU 路径对滚动行数敏感的问题就此消失。

GPU 帧构成

每帧约 1000 个实例化四边形。字形只光栅化一次进入纹理图集,之后每帧仅重新发射网格实例。

阶段 平均 说明
build 2.15 ms CPU 侧:遍历网格 → 实例四边形 + 光栅化新字形入图集 + 上传
draw 0.22 ms GL 实例化绘制
swap 2.95 ms eglSwapBuffers(呈现)
帧总计 5.32 ms ≈ 188 fps
2026-07-17 重测 · build 微优化后(ASCII 槽表、bg+glyph 合并遍历、无分配图集签名)

消除两次搬运 14 MB 的内存操作:不再有影子位图的滚动位移(~6 ms),也不再有到 dmabuf 的拷贝(~5.6 ms)—— 这 ~11 ms 就是全部的节省。GPU 直接在 EGL 表面上原地光栅化。

实测画面

语料是彩色 ANSI-SGR 混合中文、韩文与 ASCII,由基准脚本写入会话 TTY,无需触碰手机。

全屏滚动 firehose:满屏彩色 ANSI + 中文/韩文/ASCII 连续滚动
P1 · 全屏滚动 —— 满屏全损重绘的连续滚动。
空闲状态:仅光标闪烁的部分呈现帧
P2 · 空闲 —— 仅光标闪烁,局部呈现。
单行更新:8 Hz 打字,其余行逐像素保留
P3 · 单行更新 —— 8 Hz 打字,逐像素保留上方行。
基准脚本

脚本自动化三个阶段(firehose 滚动 / 空闲闪烁 / 单行更新),通过向远程主机上会话的 TTY 写入实现 —— 手机端零交互。

gpubench.sh下载 ↓
# 语料:彩色 ANSI-SGR + 中文/韩文/ASCII,400 行
corpus() {
  i=0
  while [ $i -lt 400 ]; do
    printf "\033[3%dm%04d 端末描画性能測定 中文渲染基准 가나다라마 \033[1mBOLD\033[0m ascii-abcdefghijklmnop %05d\n" \
      $((i % 8)) $i $((i * 37))
    i=$((i + 1))
  done
}
C="$(corpus)"

# P1 firehose 滚动 30s(满帧全损)
end=$((SECONDS + 30))
while [ $SECONDS -lt $end ]; do printf "%s\n" "$C" > "$T"; done

# P2 空闲 60s(仅闪烁 → 局部呈现帧)
sleep 60

# P3 单行更新 20s(~8 Hz,打字形状的局部帧)
end=$((SECONDS + 20))
while [ $SECONDS -lt $end ]; do
  printf "\rtyping simulation %06d" $n > "$T"; n=$((n + 1)); sleep 0.12
done
如何复现
  1. 打开一个到目标主机的会话;把 gpubench.sh 拷到该主机,用 who -u 找到会话对应的 TTY。
  2. 运行 ./gpubench.sh /dev/ttysNNN(会话的 tty)。
  3. 抓取:hdc -t <target> shell hilog | grep "connrender: gpu" —— 每 60 帧输出一条统计窗口。

注意:P2/P3 的统计窗口跑在低 DVFS 频率下(每秒仅 2–9 次绘制,时钟处于最低档),与 firehose 数字不可直接比较 —— 只做同节奏对比。P1 的第一个窗口包含一次性的 CJK 字形光栅化爆发(属正常)。