
鸿蒙 PC Markdown 编辑器性能工程中文输入与 10MiB 文档本文讨论中文 IME 正确性、固定语料、加载时间、完整进程组 PSS 和大文件功能降级。完整示例代码https://gitcode.com/VON-/codex_md_oh。编辑器性能要同时看时间、内存与正确性鸿蒙 PC Markdown 编辑器的性能不能只用“打开很快”来判断。大文档可能在加载时很快但在撤销、预览或 IME 组合输入时消耗大量内存。因此当前测试同时覆盖1MiB 与 10MiB UTF-8 Markdown 文档的读取和编辑器加载时间。主进程、ArkWeb 活跃进程和 ArkWeb 辅助进程的完整进程组 PSS。中文输入、撤销、重做、保存快照与修改状态。大文档连续撤销时是否出现异常退出或 LowMemoryKill。5MiB 阈值后主动降级当文档字符数达到 5×1024×1024编辑器切换到大文件模式constLARGE_DOCUMENT_CHARACTER_THRESHOLD5*1024*1024;functionupdateLargeDocumentMode(documentLength:number):void{largeDocumentModedocumentLengthLARGE_DOCUMENT_CHARACTER_THRESHOLD;if(largeDocumentModecurrentMode!source){currentModesource;workspace.dataset.modecurrentMode;previewDirtytrue;}}functioncreateEditorState(content:string):EditorState{constuseLargeDocumentSetupcontent.lengthLARGE_DOCUMENT_CHARACTER_THRESHOLD;constlineSeparatorcontent.includes(\r\n)?\r\n:\n;returnEditorState.create({doc:content,extensions:[useLargeDocumentSetup?minimalSetup:basicSetup,useLargeDocumentSetup?[]:markdown({base:markdownLanguage}),EditorState.lineSeparator.of(lineSeparator),placeholder(Start writing Markdown...),useLargeDocumentSetup?[]:EditorView.lineWrapping,EditorView.updateListener.of((update){if(!update.docChanged){return;}documentRevision1;pendingDirtyforcedDirty||!update.state.doc.eq(baselineDocument);updateLargeDocumentMode(update.state.doc.length);if(currentModesource){previewDirtytrue;}else{renderPreview(update.state.sliceDoc());}notifyNative(update.state.doc.length);scheduleRecoverySnapshot();}),EditorView.theme({:{height:100%},.cm-scroller:{overflow:auto},.cm-content:{minHeight:100%}})]});}代码来源web-editor/src/main.ts降级后使用minimalSetup关闭 Markdown 语法扩展、换行和预览模式。这是有意的产品取舍大文档首先保证能打开、能编辑和能保存而不是在极限场景中继续运行所有高成本功能。Release 模拟器实测数据指标目标实测结论1MiB 读取计入 1 秒总预算48ms通过1MiB 编辑器加载计入 1 秒总预算35ms通过1MiB 总加载≤ 1 秒83ms通过10MiB 读取计入 3 秒总预算158ms通过10MiB 编辑器加载计入 3 秒总预算187ms通过10MiB 总加载≤ 3 秒345ms通过1MiB 完整进程组 PSS 250MiB324.7MiB距目标高 29.9%10MiB 完整进程组 PSS建立技术基线396.4MiB已记录内存数据不应被描述为“全部通过”。1MiB 的 324.7MiB 高于 250MiB 正式目标只是满足预先定义的“距目标不超过 30% 且有优化路径”技术验证容差。鸿蒙 PC 大文件模式截图下图为 10MiB Markdown 文档在鸿蒙 PC / 2in1 模拟器中加载后的画面。右上角 Split 和 Preview 不可用状态栏显示Large file mode。当前结论模拟器中“鸿蒙输入测试”可以输入撤销后为空重做后恢复字数计数为 6。修复前10MiB 文档连续撤销曾触发一次LowMemoryKill修复后相同路径未产生新的异常退出。这些是可以支持架构继续前进的模拟器证据但不替代鸿蒙 PC 真机上的多次 Release P95、物理键盘长按、系统快捷键冲突和触控板滚动测试。中文输入首先是正确性问题英文键盘事件通常是一次按键对应一次可见字符中文输入法不是。用户输入拼音时浏览器会经历 composition start、update、end候选文本可能多次变化最终才提交到文档。若编辑器或快捷键处理器把组合过程当成普通按键就会出现重复字符、候选窗提前关闭、撤销粒度异常或拼音字母被直接写入正文。因此 IME 验证不能只看最后是否出现汉字还要检查完整状态组合期间候选文本不触发保存、命令面板等快捷键。候选提交后正文只出现一次目标字符。一次撤销的粒度符合用户预期不把组合过程拆成多个残片。重做能够恢复完全相同的 Unicode 文本。修改标记、字数和恢复快照以提交后的文档为准。中文后继续输入标点、英文和换行光标位置保持正确。CodeMirror 已经封装了浏览器编辑事件的大量细节但 ArkWeb 版本、鸿蒙系统 IME 和物理键盘仍会影响实际行为。浏览器自动化可以验证插入与撤销状态不能完全模拟系统候选窗真机需要覆盖全拼、双拼、中文标点、长句候选、退格修改和中英文切换。正确性指标和性能指标不能互相替代编辑器在 30ms 内显示了错误字符性能仍然是不合格输入完全正确但每次按键卡顿 500ms同样不可用。测试报告应把两类结果分开。正确性关注内容、选区、撤销、保存和格式。性能关注加载时间、输入延迟、滚动、内存和长时间稳定性。二者的交叉点是降级策略关闭语法高亮可以改善性能但不能破坏正文暂停实时预览可以减少工作量但必须明确显示当前处于 Source 模式。性能优化必须守住文档正确性回归。任何改变事务分组、Bridge 节流或大文档扩展的提交都应重新执行中文输入、撤销重做和保存快照用例而不能只比较启动时间。固定语料才能比较版本“打开一个大文件”无法复现。测试语料至少要固定字节大小、字符结构、最长行、标题密度、代码块比例、行尾和编码。两个同为 10MiB 的文件性能可能完全不同一份有十万行短文本另一份只有一个超长行软换行、语法解析和 DOM 节点数量会产生不同瓶颈。建议至少维护以下夹具1MiB 常规 Markdown中英文段落、标题、列表、链接和代码块混合。10MiB 多行文档用于大文件加载、滚动、撤销和内存基线。10MiB 超长行文档专门观察换行布局和横向滚动。大量标题文档观察 Markdown 语法树和未来大纲索引成本。中文密集文档比较字节数、UTF-16 长度、字数统计和 IME。CRLF/BOM 文档确认性能路径没有绕过格式兼容。夹具生成规则、SHA-256 和实际大小应进入报告。每轮测试使用同一文件才能判断 345ms 到 420ms 是代码回归还是语料变化。加载时间要拆分阶段总加载时间可以直接描述用户等待但只记录总数很难定位瓶颈。当前测量把文件读取和编辑器加载分开ArkTS 从授权 URI 分块读取并严格解码随后 Bridge 把正文设置到 CodeMirror页面创建 EditorState 和 EditorView。进一步可以拆成用户确认文件 → URI open/stat → 分块 read UTF-8 decode → 格式检测 → Bridge 传输 → EditorState 创建 → 首次可编辑帧 → 首次预览完成“首次可编辑”和“预览完成”不必是同一个时间点。对于较大文档可以先呈现 Source 并接受输入再延迟生成预览。测量点必须使用单调时钟避免系统时间调整多次运行要区分冷启动、热启动和文件缓存。正式门槛应采用 P95而不是挑最快一次。至少记录样本数、中位数、P95、最大值和是否存在首次运行异常。模拟器宿主机负载会显著影响数据所以模拟器适合发现数量级问题正式结论仍应来自目标鸿蒙 PC。内存要看完整进程组混合应用会同时存在 ArkTS 主进程、ArkWeb 活跃渲染进程和辅助进程。如果只读取主进程 PSSCodeMirror 文档、语法树、预览 DOM 和 JavaScript 堆都可能被遗漏。完整进程组 PSS 更接近应用实际占用。PSS 仍不是唯一指标。测试时还要关注打开文档前的稳定基线。打开 1MiB、10MiB 后的稳定值和峰值。连续撤销、重做、切换模式后的增量。关闭文档或重载后内存能否回落。是否出现 LowMemoryKill、ArkWeb 重启或明显交换。多次打开文档是否持续增长提示监听器或旧 EditorView 未释放。当前 1MiB 完整进程组 PSS 为 324.7MiB高于 250MiB 目标。正确的工程结论是“加载性能通过内存仍需优化”而不是用快速加载掩盖内存。优化时应先测各组件增量关闭预览、语法高亮、行换行或重建历史后分别比较找到真正的大项。5MiB 阈值是保护机制而不是魔法数字达到阈值后切换minimalSetup一次性减少多个高成本能力。这种做法稳定但阈值本身需要真实设备数据校准。字符长度与文件字节不完全对应结构复杂度也会影响解析和布局因此未来可以从单阈值演进为基于多信号的策略文件字节和字符长度控制读取与 Bridge 风险。行数、最大行长控制换行和滚动风险。标题、代码块等结构密度控制语法解析与预览风险。当前设备可用内存和 ArkWeb 状态决定是否延迟高成本功能。策略必须可解释。界面显示Large file modeSplit 和 Preview 保持位置但不可用用户仍可以编辑、保存和关闭。不要自动截断文档也不要只渲染一部分却让保存覆盖完整文件。输入延迟如何采样加载快不代表编辑快。大文档输入测试可以在固定位置插入单字符、中文短句和大段粘贴测量从事务发出到下一次绘制完成的时间。需要分别观察普通输入、语法解析、预览刷新、字数计算、Bridge 消息和恢复快照。优化优先级通常是先移除与每次按键成全文复杂度的工作不在每次变更跨 Bridge 传全文。大文档不扫描全文计算字数。Preview 只在可见时更新Source 模式标记为待刷新。恢复快照节流并对超大文档使用不同策略。语法解析和软换行在保护模式关闭。然后再处理更细的渲染和样式。若一个状态栏动画很顺滑却仍在每次输入复制 10MiB 字符串优化方向就是错误的。撤销重做是典型压力路径大文档连续撤销可能触发比普通输入更高的峰值因为历史中保存了变化结构视图还要重新布局。测试不能只按一次 CtrlZ应构造多次编辑、批量粘贴、连续撤销到基线、再全部重做并观察内容、脏状态和内存。修复异常退出时不能简单关闭撤销来通过性能测试。撤销是桌面编辑器核心能力合理方案是控制历史规模、减少重复全文快照、避免文档切换历史串联并对极端场景给出可预测限制。任何限制都要在产品状态或文档中明确而不是静默丢弃用户历史。真机验证矩阵鸿蒙 PC 真机至少应覆盖以下组合维度代表场景包类型Release 候选包记录 SHA-256窗口最大化、左右分屏、连续缩放输入系统中文 IME、英文、emoji、长句候选键盘内置键盘、外接键盘、长按与快捷键指针触控板滚动、选择、拖拽、触控点击文档1MiB、10MiB、多行、超长行、CRLF操作打开、输入、粘贴、撤销重做、保存、重开稳定性30 分钟编辑、多次切换、前后台与低内存每项都要记录设备型号、系统版本、HAP 哈希和样本数。真机测试不需要把每个组合无限展开但必须覆盖最可能暴露 ArkWeb、IME 和内存差异的代表场景。性能验收清单指标同时覆盖正确性、时间、内存和稳定性。测试语料固定并记录结构、大小和摘要。加载时间拆分读取、Bridge、EditorState 和首次可编辑帧。使用 Release 包多次采样报告 P50/P95 而不是最优值。内存统计包含完整 ArkWeb 进程组并观察峰值和回落。中文 IME 覆盖组合、候选、撤销、重做和保存。大文件降级保留正文完整性与基本编辑能力。任何性能优化都重新运行内容无损和保存回归。模拟器用于开发诊断正式门槛由目标鸿蒙 PC 真机复核。性能工程的最终目标不是追求一个漂亮数字而是确保用户在不同大小文档、输入方式和窗口状态下都能预测应用行为。对混合架构而言主动减少全文工作、明确降级边界、分层测量和完整进程组数据比单独优化某个动画更能决定产品上限。先建立性能预算再谈优化性能预算把总体目标分配给各阶段避免每个模块都认为自己的耗时“只有一点”。例如 1MiB 文档首次可编辑目标为一秒可以为选择器返回后的读取解码、Bridge 传输、EditorState 创建和首帧分别设置观测值不必机械平均但任何阶段持续占据大部分预算都应被定位。内存也需要预算。基线 ArkUI/ArkWeb 进程、空文档、1MiB 文档、语法树、预览 DOM、撤销历史和恢复快照分别测增量。多标签设计时用单会话增量估算上限超过目标就先选择冻结或复用不能等做完十个标签后才发现架构不可承受。预算不是一次定死。目标设备、ArkWeb 版本和功能变化后可以调整但调整要记录原因与用户影响不能为了让当前数字变绿而移动门槛。用实验矩阵定位真正成本大文档模式一次关闭多个功能适合产品保护却不利于定位。性能分析版本可以逐项对比basicSetup 与 minimalSetup、Markdown 语法扩展开关、软换行开关、预览开关、字数统计开关、恢复快照开关。每次只改变一个变量用同一 HAP 配置、语料和操作重复测量。结果应分别记录加载、输入、内存和正确性。某项扩展可能增加 30ms 加载却明显改善编辑体验不一定应删除另一项每次输入都扫描全文即使首屏影响小也应优先改造。实验目的不是证明某个库“慢”而是找到成本随文档规模增长的函数。分析完成后内部开关不应散落在正式产品中。保留清晰的大文件策略调试实验通过构建配置或测试入口管理。最长行是容易遗漏的性能变量编辑器虚拟化通常按可视行工作但一个数百 KB 的单行文本会让语法解析、选区、换行和水平滚动承受不同压力。日志、压缩 JSON、Base64 或生成代码都可能形成超长行即使总文件只有 1MiB。开启软换行时浏览器需要计算大量视觉行关闭时超宽内容又可能影响滚动与绘制。测试应在行首、中间和末尾点击、选择、输入、撤销并观察滚动条与光标。大文件策略可以在最大行长超过阈值时单独关闭换行不必等总字符达到 5MiB。Markdown 代码块中的超长行也应保持原文不能为了性能自动插入换行字符。视觉换行和文档换行必须严格区分。粘贴和替换属于峰值操作单字符输入代表稳定延迟大段粘贴和全局替换代表瞬时峰值。一次粘贴 5MiB 可能同时触发事务、语法更新、预览、字数、Bridge 和恢复任务内存短时间出现多份字符串。处理策略是先让 CodeMirror 完成一个原子事务再根据新文档规模决定是否进入大文件模式预览和统计读取最终状态不对中间版本重复工作。Bridge 只报告最新摘要恢复快照合并到下一周期。粘贴后应立即可撤销为一个合理步骤。全局替换同样要限制匹配数量和预览结果防止构造海量范围对象。替换前后内容正确性、撤销和保存必须进入压力测试。滚动性能要区分编辑区和预览区Source、Split 与 Preview 有不同滚动成本。编辑区由 CodeMirror 虚拟化预览区可能包含完整 HTML DOMSplit 同时存在两者。测试滚动时记录窗口大小、是否软换行、预览 DOM 规模和触控板输入不能只看鼠标滚轮一次移动。同步滚动如果未来实现会在两个区域间增加位置映射和事件回路。需要防止编辑区滚动触发预览、预览回调又反向触发编辑区。可以使用来源标识和动画帧合并并在大文档关闭。同步精度不应以每次滚动重新解析全文为代价。掉帧分析要结合主线程任务确认是 Markdown 渲染、布局、Bridge 还是 ArkUI 外壳更新。肉眼感觉只是发现问题的入口。长时间稳定性与内存泄漏短测试可能看不出监听器、旧 EditorView 或预览节点残留。稳定性脚本可以循环打开小/大文档、切换模式、输入撤销、保存和新建定期采集完整进程组 PSS。若每轮结束后稳定值持续上升需要检查视图销毁、定时器、Bridge 代理和恢复队列。测试还应包含前后台、锁屏恢复和 ArkWeb 进程重建。系统回收后能恢复编辑不代表没有泄漏频繁回收本身可能由内存过高触发。记录系统退出原因和 ArkWeb 进程变化避免把自动重建误认为正常稳定。长测不要求用户文档参与可使用固定无敏感夹具并在每轮校验最终哈希与内容。性能可观测性不能记录正文埋点只需要阶段时间、文档字节/字符区间、行数区间、是否大文件模式、设备和错误码。不要记录文件名、URI、标题和 Markdown。对超长行可以记录长度区间不记录内容。本地开发日志提供细粒度时间点正式版本只保留必要聚合并允许关闭。采样率和保留期限要明确。性能问题复现时由用户主动选择专用测试文档不自动上传真实资料。这样既能观察版本趋势又不会让性能优化成为隐私风险。启动、首次可编辑与完全稳定是三个指标应用窗口出现不代表用户可以输入CodeMirror 可输入也不代表预览、字数和文件树已经稳定。测量时分别记录应用首帧、编辑器就绪、文档首次可编辑和后台派生任务完成。优化优先保证用户尽快进入可编辑状态再把预览和索引延后不能为了一个更短的“启动”数字显示不可操作的空壳。冷启动包含进程和 ArkWeb 初始化热启动可能复用系统缓存。两种数据分别报告测试前明确是否强制停止应用。恢复会话启动还要单列因为读取沙箱快照和显示决策对话框属于必要工作不能与空文档混在一起。系统负载与温度会影响结论鸿蒙 PC 在电池、充电、温度和后台任务不同条件下可能调整频率与内存。正式性能采样前让设备达到稳定状态关闭无关重任务记录电源模式同时不要为了数字人为关闭产品正常依赖的系统服务。连续压力测试要观察温升后的 P95而不是只取冷机首轮。模拟器更受宿主机 CPU、内存和图形负载影响。它适合比较明显回归报告不把绝对值推广到真机。真机之间也按设备档位建立基线不用最高配置结果代表全部目标设备。性能回归阈值需要统计意识单次从 345ms 变成 365ms 可能只是噪声。回归判断应基于足够样本和分布设定绝对目标与相对变化双门槛。例如 P95 超过产品目标直接失败仍在目标内但连续多个版本上升超过一定比例则进入调查。内存也比较稳定区间和峰值不用某一秒读数。自动化环境保存历史趋势和置信范围设备异常、测试夹具变化或系统升级在图表上标注。确认回归后用实验矩阵定位不靠重复运行直到出现一次绿色结果。优化完成必须回到用户任务关闭所有扩展当然能降低内存却可能让编辑器失去价值。每项优化要回到打开、输入、滚动、撤销、预览、保存和恢复这些任务确认速度提高且功能语义不变。性能改动的验收同时包含基准数字和内容哈希、脏状态、格式、故障路径。当目标冲突时优先级是用户数据正确、安全、输入可用、可解释降级最后才是视觉效果。明确优先级可以避免为追求局部帧率引入静默内容损坏。