From 94fc1c45da41b9590d15b6b6dba205afabcc22d6 Mon Sep 17 00:00:00 2001 From: "DeepSeek-V4.1-Flash" <> Date: Wed, 4 Nov 2026 02:52:13 +0800 Subject: [PATCH] =?UTF-8?q?perf(size):=20Release=20=E5=85=B3=E9=97=AD?= =?UTF-8?q?=E5=BC=82=E6=AD=A5=E5=B1=95=E5=BC=80=E8=A1=A8=20+=20=E4=BF=AE?= =?UTF-8?q?=E6=AD=A3=20Debug=20=E6=9E=84=E5=BB=BA=E5=8F=82=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. Release 专用 `-fno-asynchronous-unwind-tables`(新增 RELEASE_ONLY_OPT,只加在 Release 的两条编译规则上)。-fno-exceptions 下绝大多数函数不再需要 .pdata/.xdata: 实测 829,440 -> 793,088 B(-36,352);.pdata 30,420 -> 12,684、.xdata 28,904 -> 10,156。 Release 不再生成可靠的栈回溯(崩溃诊断);Debug 保留完整展开表。 2. 修正真实缺陷:Makefile 的 DEBUG_OPT = -O0 从未被使用 —— Debug 两条编译规则误用了 $(RELEASE_OPT)(即 -Oz),且全程没有 -g,因此所谓 Debug 构建其实只是"不 strip 的 Release"。现在 Debug 规则改用 $(DEBUG_OPT) -g,链接也加 -g。 代价:Debug 产物 1,734,578 -> 5,992,064 B(真实 -O0 -g,属预期)。 release(全量)790KB 零警告;debug(全量 -O0 -g)零警告。 --- Documents/Code_Review_Progress.md | 26 ++++++++++++++++++++++++++ Makefile | 20 +++++++++++++++----- 2 files changed, 41 insertions(+), 5 deletions(-) diff --git a/Documents/Code_Review_Progress.md b/Documents/Code_Review_Progress.md index 2d14c97..c58e905 100644 --- a/Documents/Code_Review_Progress.md +++ b/Documents/Code_Review_Progress.md @@ -28,3 +28,29 @@ ## 节点记录 (下面按完成顺序追加) + +### P1 移除 `dynamic_cast` + 关闭 RTTI —— ✅ 完成(提交 `5de3763`) + +**改动** + +1. `Toolbar::BuildBoxes` 里唯一的 `dynamic_cast` 是**多余强转**(`Button::widget` 本来就是 + `UiButtonWidget*`)。改为直接遍历 `m_buttons`(与 `m_root->Children()` 同源同序)。 +2. 仅关 RTTI **不够**:`cp-demangle.o` 仍在链接里。真凶是 libstdc++ 的 `vterminate.o` + (引用 `__cxa_demangle`),它被 `eh_terminate.o` 的 `std::terminate` 拉入。 + ⇒ 在 `Utilities/Src/MemProbe.cpp` 里**自行定义** `__gnu_cxx::__verbose_terminate_handler()`, + 归档成员 `vterminate.o` 不再被拉入,demangler 整体消失。 + 应用启动后本来就会 `std::set_terminate` 换成自己的处理函数,行为等效。 +3. `Makefile` 新增 `NO_RTTI=1`(默认开)→ `CXXFLAGS += -fno-rtti`。 + +**实测** + +| 指标 | 改前 | 改后 | 差 | +| --- | --- | --- | --- | +| Release | 890,880 B | **829,440 B** | **−61,440 B** | +| `.text` | 753,136 B | 703,616 B | −49,520 B | +| `.rdata` | 36,936 B | 26,616 B | −10,320 B | +| Debug | 1,801,617 B | 1,734,578 B | −67,039 B | + +**验证**:release + debug **全量重建**(删 `*.o`/`*.d`)零 error 零 warning; +map 中 `cp-demangle.o` 已无 `.text` 段分配。 + diff --git a/Makefile b/Makefile index bfde428..0d2df35 100644 --- a/Makefile +++ b/Makefile @@ -201,6 +201,14 @@ ifeq ($(strip $(NO_RTTI)), 1) CXXFLAGS += -fno-rtti endif +# ---- SEH 展开表:只对 Release 关闭 `-fasynchronous-unwind-tables` ---- +# 2026-11-04 审查实测:**只对 Release** 关闭后产物从 829,440 → 793,088 B(**−36,352 B**), +# 因为 `-fno-exceptions` 下绝大多数函数不再需要 `.pdata`/`.xdata`。 +# * `.pdata` 只用于栈回溯(崩溃诊断);本程序不打印栈回溯,功能不受影响。 +# * ⚠️ 代价:Release 崩溃时 WER 拿不到可靠调用栈(Debug 构建保留完整展开表)。 +# * ⚠️ 全关(`-fno-unwind-tables`)会链接失败(历史踩坑),**不要**打开。 +RELEASE_ONLY_OPT = -fno-asynchronous-unwind-tables + # 丢弃未被引用的函数/数据(非 LTO 时还需要配合 -ffunction-sections 才有粒度)。 GC_SECTIONS = -Wl,--gc-sections @@ -285,18 +293,18 @@ $(BUILD_DIR)/$(SUB_DIR_RELEASE)/$(TARGET_FILE_NAME).exe: $(RELEASE_OBJECTS) # Debug 最终可执行文件编译任务 $(BUILD_DIR)/$(SUB_DIR_DEBUG)/$(TARGET_FILE_NAME).exe: $(DEBUG_OBJECTS) @echo ====== [Debug] All File Compiled. Now Linking... ====== - $(CXX_COMPLIER) $(DEBUG_OBJECTS) -static -o $@ $(LIB_LINK) $(LDFLAGS) + $(CXX_COMPLIER) $(DEBUG_OBJECTS) -static -g -o $@ $(LIB_LINK) $(LDFLAGS) @echo ====== [Debug] Program Link Finished ====== # C Release 目标文件编译 $(BUILD_DIR)/$(SUB_DIR_RELEASE)/%.o: %.c Makefile | $(BUILD_DIR)/$(SUB_DIR_RELEASE) @echo ====== [Release] C Source File "$<" Compiling... ====== - $(C_COMPLIER) -c $(CFLAGS) $(RELEASE_OPT) $(ASM_LISTING_C) $< -o $@ + $(C_COMPLIER) -c $(CFLAGS) $(RELEASE_OPT) $(RELEASE_ONLY_OPT) $(ASM_LISTING_C) $< -o $@ # C++ Release 目标文件编译 $(BUILD_DIR)/$(SUB_DIR_RELEASE)/%.o: %.cpp Makefile | $(BUILD_DIR)/$(SUB_DIR_RELEASE) @echo ====== [Release] C++ Source File "$<" Compiling... ====== - $(CXX_COMPLIER) -c $(CXXFLAGS) $(RELEASE_OPT) $(ASM_LISTING) $< -o $@ + $(CXX_COMPLIER) -c $(CXXFLAGS) $(RELEASE_OPT) $(RELEASE_ONLY_OPT) $(ASM_LISTING) $< -o $@ # Release 资源脚本文件编译 $(BUILD_DIR)/$(SUB_DIR_RELEASE)/%.o: %.rc Makefile | $(BUILD_DIR)/$(SUB_DIR_RELEASE) @@ -304,14 +312,16 @@ $(BUILD_DIR)/$(SUB_DIR_RELEASE)/%.o: %.rc Makefile | $(BUILD_DIR)/$(SUB_DIR_RELE $(WIN_RES_COMPLIER) -c $(WIN_RESOURCE_CODEPAGE) $(foreach path,$(WIN_RESOURCE_INCLUDES_PATHS),$(addprefix -I,$(path))) $< -o $@ # C Debug 目标文件编译 +# ⚠️ 2026-11-04 审查修正:原来这里误用了 `$(RELEASE_OPT)`,导致 `DEBUG_OPT = -O0` +# **从未生效**(Debug 实际上也是 -Oz,且不带 `-g`,根本无法调试)。 $(BUILD_DIR)/$(SUB_DIR_DEBUG)/%.o: %.c Makefile | $(BUILD_DIR)/$(SUB_DIR_DEBUG) @echo ====== [Debug] C Source File "$<" Compiling... ====== - $(C_COMPLIER) -c $(CFLAGS) $(RELEASE_OPT) $(ASM_LISTING_C) $< -o $@ + $(C_COMPLIER) -c $(CFLAGS) $(DEBUG_OPT) -g $(ASM_LISTING_C) $< -o $@ # C++ Debug 目标文件编译 $(BUILD_DIR)/$(SUB_DIR_DEBUG)/%.o: %.cpp Makefile | $(BUILD_DIR)/$(SUB_DIR_DEBUG) @echo ====== [Debug] C++ Source File "$<" Compiling... ====== - $(CXX_COMPLIER) -c $(CXXFLAGS) $(RELEASE_OPT) $(ASM_LISTING) $< -o $@ + $(CXX_COMPLIER) -c $(CXXFLAGS) $(DEBUG_OPT) -g $(ASM_LISTING) $< -o $@ # Debug 资源脚本文件编译 $(BUILD_DIR)/$(SUB_DIR_DEBUG)/%.o: %.rc Makefile | $(BUILD_DIR)/$(SUB_DIR_DEBUG)