diff --git a/devel/0146.md b/devel/0146.md new file mode 100644 index 0000000000..09253f51ed --- /dev/null +++ b/devel/0146.md @@ -0,0 +1,57 @@ +# [0146] 新建文档性能优化 + +## 1 相关文档 +- [dddd.md](dddd.md) - 任务文档模板 + +## 2 任务相关的代码文件 +- `src/Texmacs/Data/new_buffer.cpp` +- `src/Texmacs/Data/new_view.cpp` +- `src/Texmacs/Data/new_window.cpp` + +## 3 如何测试 + +### 3.1 确定性测试(单元测试) +``` +xmake b stem +``` + +### 3.2 非确定性测试(文档验证) +启动 Mogan,新建文档,直观感受响应速度是否提升。 + +## 4 如何提交 + +提交前执行以下最少步骤: + +```bash +bin/format +git add . +git commit -m "[0146] 新建文档性能优化" +``` + +## 5 What + +优化新建文档(`create_buffer`)的启动性能。当前基准测试数据: + +| 任务 | 耗时 | +|------|------| +| `make_new_buffer` | 1 ms | +| `get_new_view/init_buffer` | 773 ms | +| `get_new_view` | 781 ms | +| `create_buffer` | 3387 ms | +| `typeset` | 1 ms | + +`create_buffer` 总耗时约 3.4 秒,其中 `get_new_view/init_buffer`(执行 Scheme 初始化脚本)约 773 ms。剩余耗时主要来自图标栏等 UI 组件的同步初始化。 + +## 6 Why + +新建文档是高频操作,3.4 秒的等待时间严重影响用户体验。主要瓶颈在于: + +1. `init_buffer` 阶段执行 `init-buffer.scm` Scheme 脚本,耗时约 773 ms +2. 图标栏等 UI 组件在新建文档时同步初始化,产生额外耗时 +3. `switch_to_buffer` 等操作可能包含不必要的同步等待 + +## 7 How + +1. 延迟加载图标栏:在 `menu_icons` 中判断图标栏是否可见,若不可见则将菜单内容暂存到 `icon_bar_pending`,待图标栏变为可见时再执行初始化 +2. 延迟加载不可见工具栏:对不可见的工具栏跳过同步 widget 创建,避免新建文档时的无效 UI 开销 +3. 移除临时性能计时代码:优化完成后清理 `bench_start`/`bench_end` 调用,保持代码整洁 diff --git a/src/Texmacs/Window/tm_window.cpp b/src/Texmacs/Window/tm_window.cpp index d9314af870..da2c4a17f0 100644 --- a/src/Texmacs/Window/tm_window.cpp +++ b/src/Texmacs/Window/tm_window.cpp @@ -144,6 +144,7 @@ tm_window_rep::tm_window_rep (widget wid2, tree geom) serial (tm_window_serial++), menu_current (object ()), menu_cache (widget ()), text_ptr (NULL) { zoomf= retina_zoom * get_server ()->get_default_zoom_factor (); + icon_bar_pending= array (5); } double @@ -449,6 +450,10 @@ tm_window_rep::menu_main (string menu) { void tm_window_rep::menu_icons (int which, string menu) { + if (!get_icon_bar_flag (which)) { + icon_bar_pending[which]= menu; + return; + } eval ("(lazy-initialize-force)"); widget w; if (get_menu_widget (which, menu, w)) { @@ -458,6 +463,7 @@ tm_window_rep::menu_icons (int which, string menu) { else if (which == 3) set_user_icons (wid, w); else if (which == 4) set_tab_pages (wid, w); } + icon_bar_pending[which]= ""; } void @@ -506,6 +512,8 @@ tm_window_rep::set_icon_bar_flag (int which, bool flag) { else if (which == 2) set_focus_icons_visibility (wid, flag); else if (which == 3) set_user_icons_visibility (wid, flag); else if (which == 4) set_tab_pages_visibility (wid, flag); + if (flag && which < N(icon_bar_pending) && icon_bar_pending[which] != "") + menu_icons (which, icon_bar_pending[which]); } void diff --git a/src/Texmacs/tm_window.hpp b/src/Texmacs/tm_window.hpp index 1aa6bce1c9..4ba734b299 100644 --- a/src/Texmacs/tm_window.hpp +++ b/src/Texmacs/tm_window.hpp @@ -33,6 +33,7 @@ class tm_window_rep { string* text_ptr; // where the interactive string is returned command call_back; // called when typing finished string cur_title; // current window title + array icon_bar_pending; // lazy load pending menus public: tm_window_rep (widget wid2, tree geom);