Repository navigation
Replies: 1 comment 3 replies
EnglishBefore adding another caching or paint-replay mechanism to the GPUI backend, I’d prefer to evaluate NSH’s existing platform-native backends for Maka desktop. On macOS, the AppKit backend already uses per-node, layer-backed views. That looks like a more direct way to avoid the surface-wide painting path you identified. Please start with macOS: compare the same small animation case, then a real streaming conversation, using the same release profile, window size and display refresh rate. Measure process CPU, RSS and frame times before deciding the next step. Keep the Host and shared TSX UI intact. The work should focus on desktop-shell integration and any missing native-backend embedding APIs needed to reuse our engine configuration, Host bindings and dynamic asset/module loading. For repository ownership: 简体中文在给 GPUI 后端增加另一套缓存或绘制回放机制之前,我更倾向于先评估 NSH 已有的平台原生后端是否更适合 Maka desktop。 macOS 的 AppKit 后端已经使用每个节点独立的 layer-backed view,从结构上看,更直接地避开了你指出的整个 surface 重复绘制路径。请先从 macOS 开始:用相同的 release 配置、窗口大小和显示刷新率,对比这个小动画场景,再测真实流式对话,记录进程 CPU、RSS 和帧耗时,再决定下一步。 保留现有 Host 和共享 TSX UI,改动集中在 desktop-shell 接入,以及原生后端为复用现有 engine 配置、Host bindings、动态资源和模块加载所缺少的嵌入接口上。 代码维护位置也说明一下: |
Uh oh!
There was an error while loading. Please reload this page.
Problem. NSH's GPUI backend draws each surface with one element, and its
paintwalks the whole tree (render::draw_view). Whatever changed, every frame repaints everything visible. Agents produce frames constantly: streaming text, tool progress and status changes. Moving away from Electron does not remove this cost by itself.Measurement. Release build on a MacBook Pro built-in display: a 1280×821 window with 32 lines of text and three animated dots. Each mode ran two 20-second phases. CPU is the share of one core for the Maka process; GPU is system-wide, with other apps open.
Animated.loopAnimatedValue.setAnimatedValue.setThe native loop runs no JS per frame, yet it costs the most because it redraws the whole tree on every display frame.
inactive_frame_interval: Nonekeeps that rate when the window loses focus. In a fully occluded window, all modes stayed at or below 0.4%.Not measured yet: streaming text, a long real transcript, or a window attached to many running sessions (the desktop validation still open in #6078).
Options.
Entity::cached, whichgpui-fastalready has. The hard parts are that one element owns the surface, transforms and opacity live inDrawCx, and event listeners are installed during paint.NshViewand replay the unchanged ones. This is more general, but may need newgpui-fastAPI.Questions for @M4n5ter.
longbridge/nsh, your fork, orthird-party/nsh?问题。 NSH 的 GPUI 后端用一个元素绘制整个 surface,它的
paint会遍历整棵树(render::draw_view)。无论改了什么,每一帧都要重画所有可见内容。Agent 又会持续产生新帧:流式文字、工具进度、状态变化。离开 Electron 并不会自动消除这项成本。测量。 Release 构建,MacBook Pro 内建屏幕,1280×821 窗口,32 行文字加三个动画点。每种模式跑两轮,每轮 20 秒。CPU 是 Maka 进程占单核的比例;GPU 是全系统占用,当时还开着其他应用。
Animated.loopAnimatedValue.setAnimatedValue.set原生循环每帧不运行 JS,却最贵,因为它在每个显示帧都重绘整棵树。
inactive_frame_interval: None让窗口失焦后也保持这个帧率。窗口被完全遮挡时,各模式的 CPU 都不超过 0.4%。还没测: 流式文字、真实长对话、连着大量运行中会话的窗口(也就是 #6078 里还没做的桌面验证)。
可选方向。
gpui-fast已有的Entity::cached把 surface 切成多个区块。难点是一个元素独占 surface,变换和透明度都在DrawCx里,事件监听也是在绘制时安装的。NshView记录绘制图元,未变化的直接回放。这个方向更通用,但可能需要gpui-fast增加 API。想请 @M4n5ter 一起看的问题。
longbridge/nsh、你的 fork,还是third-party/nsh开始?All reactions