Ghostty libghostty-vt:C 语言实现 Scrollback 增量压缩——活动令牌与调用方驱动调度

发布时间:2026/9/6 21:41:48
Ghostty libghostty-vt:C 语言实现 Scrollback 增量压缩——活动令牌与调用方驱动调度 Ghostty libghostty-vtC 语言实现 Scrollback 增量压缩——活动令牌与调用方驱动调度【免费下载链接】ghostty Ghostty is a fast, feature-rich, and cross-platform terminal emulator that uses platform-native UI and GPU acceleration.项目地址: https://gitcode.com/GitHub_Trending/gh/ghostty本文围绕 Ghostty 官方示例c-vt-compression展开讲解嵌入应用embedding application如何基于 libghostty-vt 的 C API 实现 Scrollback 增量压缩通过缓存ghostty_terminal_compression_activity返回的压缩活动令牌来检测终端变化、用自己的空闲定时器idle timer调度ghostty_terminal_compress的增量压缩步骤并正确处理 PENDING / COMPLETE / UNSUPPORTED 三种调度结果。读完后你能在自研终端或终端组件中落地“空闲期后台压缩 scrollback”的完整模式并理解其源码层面的设计约束。1. 示例定位libghostty-vt 不做调度调度权在嵌入方example/c-vt-compression这个示例演示的核心问题非常明确当一个应用把 libghostty-vt 作为库嵌入时如何在不阻塞前台 I/O 的前提下对终端 scrollback回滚缓冲做压缩。官方 READMEexample/c-vt-compression/README.md点出了两条设计基线这两条是整个模式的前提压缩是调用方驱动的caller-drivenlibghostty-vt 不会自己创建定时器也不会起后台线程。何时压、压多少完全由嵌入应用自己决定。嵌入应用负责两件事调度scheduling用自己的空闲定时器决定何时发起压缩串行化serialization压缩调用必须与终端的其他访问写入、渲染、搜索等串行执行因为ghostty_terminal_compress对同一终端的其他操作不是线程安全的见 include/ghostty/vt/terminal.h 中的函数注释。运行示例本身很简单进入示例目录后执行zig build run即可完整流程建终端 → 写入可压缩历史 → 追踪活动令牌 → 模拟空闲压缩循环都由单文件 main.c 演示。2. C API 全景压缩相关的三个核心接口Scrollback 压缩在 C 头文件 include/ghostty/vt/terminal.h 中由三块构成先建立这张全景表后面逐节对照源码。2.1 压缩模式GhosttyTerminalCompressionMode枚举值含义GHOSTTY_TERMINAL_COMPRESSION_MODE_INCREMENTAL执行一步有界bounded的压缩工作适合空闲回调调度这是示例采用的模式GHOSTTY_TERMINAL_COMPRESSION_MODE_FULL同步地扫描当前所有符合条件的页在大规模 scrollback 上可能造成卡顿头文件明确提示 can stall on large scrollback buffers2.2 调度结果GhosttyTerminalCompressionResult枚举值语义嵌入方应对GHOSTTY_TERMINAL_COMPRESSION_RESULT_PENDING仍有增量压缩工作未完成保持终端空闲时再发起下一步GHOSTTY_TERMINAL_COMPRESSION_RESULT_COMPLETE本轮 pass 已无后续可调度停止压缩回到等待“活动令牌变化”GHOSTTY_TERMINAL_COMPRESSION_RESULT_UNSUPPORTED当前目标平台不可用头文件注释Retained-mapping reclamation is unavailable on this target视为终态不再调度2.3 两个函数// 读取压缩活动令牌只观察不执行任何压缩 GhosttyResult ghostty_terminal_compression_activity( GhosttyTerminal terminal, uint64_t* out_activity); // 压缩符合条件的 scrollback GhosttyResult ghostty_terminal_compress( GhosttyTerminal terminal, GhosttyTerminalCompressionMode mode, GhosttyTerminalCompressionResult* out_result);活动令牌的使用约束来自头文件注释include/ghostty/vt/terminal.h 中ghostty_terminal_compression_activity的文档令牌是不透明的只有相等性比较有含义嵌入方应缓存它值变化时重启自己的压缩空闲延迟而不是在输出路径上直接压缩令牌可以回绕wrap变大变小含义相同该函数只观察终端状态不执行也不调度压缩终端句柄为 NULL 时返回GHOSTTY_INVALID_VALUE。而ghostty_terminal_compress的注释补充了两条重要的语义边界压缩是**机会主义opportunistic**的COMPLETE表示pass 结束了不保证每一页都被压缩——某些页可能压缩收益不足unprofitable也可能遇到分配或回收失败压缩只改变终端的存储表示绝不改变逻辑内容也不影响 scrollback 上限访问已压缩的历史会被透明地恢复。3. 示例源码逐段精读完整的压缩调度模式下面按 main.c 的实际结构走一遍。3.1 创建终端并设置 scrollback 上限GhosttyTerminal terminal; GhosttyResult result ghostty_terminal_new(NULL, terminal, 80, 24); assert(result GHOSTTY_SUCCESS); size_t max_scrollback_bytes 10 * 1024 * 1024; result ghostty_terminal_set( terminal, GHOSTTY_TERMINAL_OPT_SCROLLBACK_MAX_BYTES, max_scrollback_bytes); assert(result GHOSTTY_SUCCESS);示例以 80×24 创建终端并通过ghostty_terminal_set把 scrollback 上限设为 10 MiBGHOSTTY_TERMINAL_OPT_SCROLLBACK_MAX_BYTES。这个上限设定了对压缩有意义的前提只有存在受上限约束的大缓冲压缩省下的存储才有实际价值。3.2 追踪压缩活动token 比较而非直接压缩uint64_t compression_activity; result ghostty_terminal_compression_activity(terminal, compression_activity); assert(result GHOSTTY_SUCCESS); // 终端变化可能使 token 改变。改变时重启应用自己的空闲定时器 // 而不是在输出路径上直接压缩。 const char *line repeated and compressible terminal history\r\n; for (size_t i 0; i 4000; i) { ghostty_terminal_vt_write(terminal, (const uint8_t *)line, strlen(line)); } uint64_t new_activity; result ghostty_terminal_compression_activity(terminal, new_activity); assert(result GHOSTTY_SUCCESS); if (new_activity ! compression_activity) { compression_activity new_activity; // 在这里重启应用的压缩空闲定时器。 }这段是 README 强调的模式核心写入前后各取一次活动令牌做相等比较变了就重置空闲定时器。示例特意写入了 4000 行重复文本repeated and compressible terminal history制造大量可压缩的 scrollback 历史。源码注释还点明了一个工程细节比较发生在输出路径之外——真实应用中通常是在处理完一批 PTY 输出后顺带检查一次 token而不是每写一个字节就压缩。3.3 空闲步骤一次有界的增量压缩//! [compression-idle-step] // 在应用的空闲定时器触发后执行一步。返回 true 表示 // 只要终端仍空闲应用应继续调度下一步。 static bool compression_idle_step(GhosttyTerminal terminal) { GhosttyTerminalCompressionResult compression_result; GhosttyResult result ghostty_terminal_compress( terminal, GHOSTTY_TERMINAL_COMPRESSION_MODE_INCREMENTAL, compression_result); assert(result GHOSTTY_SUCCESS); switch (compression_result) { case GHOSTTY_TERMINAL_COMPRESSION_RESULT_PENDING: return true; case GHOSTTY_TERMINAL_COMPRESSION_RESULT_COMPLETE: case GHOSTTY_TERMINAL_COMPRESSION_RESULT_UNSUPPORTED: return false; default: assert(false); return false; } } //! [compression-idle-step]这个函数把 2.2 节的结果表落成了代码PENDING→ 返回true请空闲调度器再来一步COMPLETE/UNSUPPORTED→ 返回false本轮结束其他值 → 断言失败防御未知枚举值。注意断言的是GhosttyResult调用是否成功而业务分支走的是GhosttyTerminalCompressionResult调度语义——两层返回值各司其职这在 C API 中是通用约定。3.4 主循环模拟空闲定时器// 模拟空闲定时器及其短暂的 pending 工作续延。 while (compression_idle_step(terminal)) {} ghostty_terminal_free(terminal); return 0;while循环就是在模拟空闲定时器反复触发只要还PENDING就继续压直到COMPLETE。真实应用中这个循环体不会在一个函数里转完而是由定时器每次触发执行一步与前台 I/O 交替进行。4. 源码纵深压缩落在终端页层从源码结构看压缩的实体实现位于 src/terminal/compress/ 目录包含Page.zig、lz4.zig、lz4_differential.zig三个文件。可以推断scrollback 以页page为单位存储与压缩压缩算法基于 LZ4 并带有差分differential压缩路径——这也解释了头文件中pages may be unprofitable的说法压缩是逐页决策的某页若压后不划算或资源不足就跳过而不是报错。两个值得留意的工程事实压缩不影响逻辑内容C API 注释明确Compression changes only the terminals storage representation and never its logical contents or scrollback limit且Accessing compressed history restores it transparently。也就是说嵌入方不需要感知解压缩——滚动查看、搜索历史时自动透明恢复业务代码零改动。性能验证入口仓库自带 scrollback 压缩基准测试 src/benchmark/ScrollbackCompression.zig可结合src/benchmark/下的 CLI 选项运行用于评估压缩路径的实际开销C 侧 API 的封装实现在 src/terminal/c/terminal.zig 中头文件注释中的snippet标注compression-activity、compression-idle-step说明 Doxygen 文档与示例源码是联动维护的。5. 嵌入实践清单把示例搬进真实应用结合示例与头文件约束一个生产级的调用方应当做到要点依据做法空闲才压缩README / 头文件用应用自己的 idle timer输出活跃期间不触发ghostty_terminal_compresstoken 驱动重启定时器main.c批处理输出后比较compression_activity变化则重置空闲延迟只比较相等性增量模式优先terminal.hINCREMENTAL有界、可续延FULL是同步全扫描大缓冲会卡仅在可控场景如退出前、空闲窗口充裕使用串行化访问头文件 not thread-safe 注释压缩与vt_write、渲染、搜索等在同一执行域内互斥切勿另开后台线程直接调用容忍压不完全opportunistic 语义不要把COMPLETE当全部压缩成功UNSUPPORTED是平台能力问题静默降级即可先设 scrollback 上限示例的GHOSTTY_TERMINAL_OPT_SCROLLBACK_MAX_BYTES用ghostty_terminal_set在会话早期配置10 MiB 可作为参考量级6. 小结c-vt-compression示例的价值在于它给出了一套最小但完整的 caller-driven 压缩调度模式用不透明活动令牌做是否该重启空闲计时的判断用有界的INCREMENTAL步骤做每次只做一点的执行用PENDING/COMPLETE/UNSUPPORTED三态闭环做是否继续的决策。libghostty-vt 刻意不内置定时器与后台线程把调度主权留给嵌入应用——这既保证了库在无 UI 事件循环环境C/C/WASM 嵌入下的可移植性也要求嵌入方理解并接受压缩是机会主义的、访问历史是透明的这两条语义。配套入口示例与构建脚本见 example/c-vt-compression/API 声明见 include/ghostty/vt/terminal.h压缩实现见 src/terminal/compress/性能基准见 src/benchmark/ScrollbackCompression.zig。【免费下载链接】ghostty Ghostty is a fast, feature-rich, and cross-platform terminal emulator that uses platform-native UI and GPU acceleration.项目地址: https://gitcode.com/GitHub_Trending/gh/ghostty创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考