Repository navigation
Square 0.2.0
Square 0.2.0 是以性能优化为主的版本。相对 0.1.0,改动集中在四条热路径:布局与排版(保留式 flex 节点、字体度量与滚动条缓存、布局失效不再强制全帧)、绘制与 CSS 动画(数值叠加层、变换矩形覆盖光栅化、Win32 高精度帧调度)、文本光标,以及代码编辑器分词缓存。同一区间还新增了 Godot 后端、核心 HTML5 元素渲染、静态 HTML 外壳组件挂载和 DevTools 原生 Chrome 检查。发布 22 个统一版本的 Wuldas.Square / Wuldas.Square.* 框架及模板包,面向 .NET 10。项目仍处于实验阶段,公共 API 和模板语法可能继续调整。
布局优化
- 保留式外部 flex 布局:按根保留 Yoga 节点树与滚动条 gutter 收敛快照,只在结构、布局上下文或宽度模式变化时重建,宽度变化走增量更新;收敛快照字典按排列深度复用,比较和会话分离时清空元素引用,避免每帧重新建树和分配字典。
- 字体度量缓存:系统字体度量按 family、size、weight、style、自定义字体集合代次和平台度量提供器代次缓存(上限 256 项)。命中后不再重复创建 GDI DC 与字体对象;注册或替换字体、替换平台提供器后,旧缓存不会遮蔽新度量。
- 滚动条样式与几何缓存:overflow / scrollbar 样式快照使用独立的样式版本,Body 同时检查文档根的版本与身份;滚动条几何缓存还校验元素矩形、内容尺寸、滚动偏移、设备配置、可见性和伪元素样式版本,不能靠缓存跳过这些失效。
- 布局失效不再强制全帧:Composite 与 Paint 的失效被拆分,显示命令跨帧保留,普通布局脏区只重绘屏幕空间中新旧 AABB 分块。仅当显示树拓扑变化、可视边界未知或后端目标要求完整重绘时才回退全帧。
display: none子元素不再贡献滚动内容范围,重新显示后重新参与布局。- 固定窗口外壳改为单次测量与排列的组合入口,在保持 Head/Body 标题语义和绝对原点的前提下完成布局,不再让外壳与内容各自走一套排列路径。
- 修正 body 的 relayout 高度与文档滚动:auto 高度在 relayout 期间保持包含块剩余高度,布局失效后不再把 scrollTop 清零导致文档跳回顶部;滚轮滚动位置可跨失效保留,body 可直接滚动文档视口。
- 内联、表格与表单控件排版对齐:保留块级到内联的 margin,表格按网格定宽,input / button 与文本基线对齐,桌面默认按钮绘制 UA 3D 边框并在按下时明显变暗。
绘制、动画与帧调度
- 动画数值叠加层:width、transform、opacity 等动画数值直接送入布局与绘制,不再每帧把数值格式化成字符串再解析,同时保留量化和相等判断以避免无意义失效。
- 变换矩形光栅化:软件后端对旋转/斜切填充按原 2×2 子像素覆盖采样,只混合被覆盖的像素;内部全覆盖区间只是性能提示,两端必须用原浮点采样表达式验证,否则回退逐像素。两个后端都增加了 solid-leaf 不透明度快路径。
- Direct2D 保留 HWND 目标以支持局部渲染;
SQUARE_DIRECT2D_REQUIRE_HARDWARE=1可强制硬件目标,避免后端对比测到软件路径。 - Win32 帧泵改用高精度 one-shot waitable timer 与
MsgWaitForMultipleObjectsEx同时等待帧截止时间和窗口消息:不忙等、不追赶补交错过的帧,最小化时停钟,消息泵退出后释放句柄;VSync=false由 Win32 宿主自行掌握提交节奏。 - CSS 动画与变换:transform 同时参与绘制、边界与动画;样式重放保留动画进度和带单位的关键帧值;scoped 数值关键帧正确导出到 Web CSS。
代码编辑器与文本
- 检查点缓存改用内置 SortedList 二分定位,按需剪枝,去掉热命中的全量检查点扫描及分配。
- 过渡行只推进状态,减少逐行字典写入与修剪;旧缓存窗口保留至批次结束,避免重复分词。
- 固定 1024 个非零检查点预算内保留稀疏全局恢复点与目标附近密集点,减少大文件旧区域回跳时从头重算。
- 增量行起点与最大行宽缓存:普通输入不再触发全文档扫描,10 万行文档(关闭折叠)输入 p95 保持在 50 ms 以内。
- 光标只在闪烁边沿重绘,并且只失效光标矩形,去掉 16 ms 的透明度过渡 tick。
- 共享
CodeEditorTextModel支持多视图文档与事务性内容变更,Win32WM_CLOSE可在销毁前取消。 - 分词缓存新增跨行状态、EOF、失效、容量、异常恢复和全局保留策略测试;完整代码编辑器套件 190 项通过。
测量结果
布局与 CSS 动画工作负载
720 个 box(transform / opacity / width 三组各 240)在 900×1240 视口内做不变的 6 秒线性循环,预热后连续 5 轮、每轮 30 秒,取中位数。环境为 Intel Core i5-12400F、Windows 11、.NET 10.0.11。
| 目标 | 优化前单核 CPU | 优化后单核 CPU | 变化 | 优化后 FPS |
|---|---|---|---|---|
| Square Software JIT | 80.2% | 56.8% | −29.2% | 60.0 |
| Square Direct2D JIT | 49.3% | 37.5% | −23.9% | 60.0 |
| Square Software NativeAOT | 92.2% | 70.0% | −24.1% | 60.0 |
| Square Direct2D NativeAOT | 68.2% | 45.3% | −33.6% | 60.0 |
| Avalonia(未改动的对照) | 28.7% | 27.4% | −4.4% | 59.9 |
单核 CPU 指进程 CPU 时间除以墙钟时间,按一个逻辑处理器折算。这是同一协议下的优化前/后原始观测,不是控制变量校准后的因果结论;未被改动的 Avalonia 仍出现 4.4% 波动,可作为环境噪声参考。Square 的单核 CPU 仍高于同批次 34.62% 的验收阈值,本轮 CPU 目标未达成。FPS 统计的是 FramePresented 渲染提交次数,不是屏幕扫描帧数;Direct2D 测量使用硬件目标,未采样 GPU 引擎占用与专用显存。完整数据与限制见 results.json。
分词缓存
在 i5-12400F、Windows、.NET 10.0.11 的百万行混合 C# 文本上,对比本轮全局保留策略与前阶段已经优化的缓存:
| 场景 | 前阶段/ms | 0.2.0/ms | 重新分词行数 |
|---|---|---|---|
| 真实 TextMate 回跳至第 8,192 行 | 1,727.7 | 434.2 | 8,192 → 2,048 |
| 合成分词器回跳文档中部 | 40.94 | 0.0285 | 500,000 → 288 |
| 合成分词器文档中部失效重读 | 33.13 | 0.0387 | 500,065 → 353 |
真实与合成分词器的结果不能相互替代。以上是指定分词轨迹的样本中位数,不是 UI 帧时间;全局检查点只覆盖已成功扫描且未被失效删除的状态,首次加载仍需建立跨行状态。已缓存读取保持零托管分配。完整数据与复现方法见检查点报告。
同期新增能力
- Godot 后端:新增
Wuldas.Square.Backends.Godot/Wuldas.Square.Platform.Godot及示例,并抽出跨后端共享的镶嵌(tessellation)路径。 - 核心直接渲染 HTML5 元素;新增类型化元素与命名空间解析,编译器和语言服务器做项目级模板分析。
- 本地静态 HTML 外壳与编译组件挂载(
--html-file,挂载到#sqx-root/#sqv-root),卸载后永久释放绑定与生成样式。 - DevTools 原生 Chrome 检查与运行时编辑:DOM 实时同步、原生 overlay 选取、原子 CSS 编辑与计算样式跟踪、托管 Console 捕获、确定性连接关闭。
- 语言服务器:补全项携带 markdown 文档,协议错误不再导致进程退出,协商位置编码与悬停/定义能力;TextMate 语法修复指令闭合标签、嵌套 slot template 与 sqv 指令值作用域。
- 控件与渲染修正:
ForNode批量通知合并(修复 Clear + Add 重复渲染,issue #14)、表单控件渲染对齐、旋转矩形按覆盖光栅化。
安装
dotnet new install Wuldas.Square.Templates@0.2.0
dotnet new square -n MyApp
dotnet run --project MyApp现有应用升级时,将框架、编译器、平台及扩展包统一升级至 0.2.0。完整用法见入门指南。
支持边界
- Windows / Win32 与 Linux / X11 是主要验证的桌面宿主;macOS 也包含在桌面 CI 中。
- Android 仍为 Experimental;arm64 真机和官方 NativeAOT 的既有限制保持。
- 上述布局与分词优化没有新增生产依赖,没有改动 tokenizer 的公共接口,也没有实现后台或分批高亮;保留式 flex 缓存只在桌面应用会话内启用,独立创建
LayoutEngine时仍走原来的临时 Yoga 会话。
发布产物由版本标签构建、校验内部依赖和模板包版本,并通过 NuGet Trusted Publishing 发布。正式标签为 v0.2.0。