From ac0d0f2cc8c30df4a168a155fdd7063aee8a41e6 Mon Sep 17 00:00:00 2001 From: TermiNexus Date: Tue, 29 Sep 2026 14:41:48 +0800 Subject: [PATCH] =?UTF-8?q?perf(tpc):=20=5FMemberSlotAccepts=20=E8=BA=AB?= =?UTF-8?q?=E4=BB=BD=E7=9F=AD=E8=B7=AF=20+=20=5Fgenerate=5Fstructs=20?= =?UTF-8?q?=E7=83=AD=E8=B7=AF=E5=BE=84=E5=B1=80=E9=83=A8=E5=8C=96=EF=BC=88?= =?UTF-8?q?profile=20=E7=AC=AC=E4=BA=8C=E6=A2=AF=E9=98=9F=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 依据 PROF/main_prof_10152.prof(tottime 2288.9s / 72 文件顺序翻译): _generate_structs 自身 268.6s cum 1893.2s 15762 基本/35240 总调用 └ 子调用:_TryLoadStructFromStub 1589.5s×418k、_MemberSlotAccepts 61.1s×54.2M isinstance 39.7s×300M、PointerType 构造 68.7s×15.9M、 SymbolTable.lookup 16.7s×15.9M、__len__ 6.8s×15.9M 本次两处(均等价改写): 1. StructGen._MemberSlotAccepts:在 `Declared == Slot or str(Declared) == str(Slot)` 之前加**身份短路** `Declared is Slot`。该函数被 _generate_structs 调 54.2M 次, 其中 llvmlite `Type.__eq__` 合计 ~30s(types.py:178/303/550/720)+ `str()` ~3.3s;同一对象(body 与 class_members 引用同一类型对象)是其常见形态。 2. StructGen._generate_structs:把 `self.SymbolTable` / `.lookup` 提升为函数级局部 (真值语义逐字保持:SymbolTable 定义了 __len__,故先取 `bool(_symtab)`), 消掉逐类重复的属性查找与 15.9M 次 `__len__`。 说明:本提交只做等价微优化;本函数的大头(35,240 次全量 O(类数×成员数) 扫描、 429k 次结构体 stub 加载、1407 次泛型特化整类发射)需要结构性改动,另行评估。 --- lib/core/LLVMCG/StructGen.py | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/lib/core/LLVMCG/StructGen.py b/lib/core/LLVMCG/StructGen.py index ee3e01f..15ccbb3 100644 --- a/lib/core/LLVMCG/StructGen.py +++ b/lib/core/LLVMCG/StructGen.py @@ -303,6 +303,11 @@ class StructGenMixin: """ if Declared is None or Slot is None: return True + # 同一对象直接放行:llvmlite 的 Type.__eq__ 走类型键比较(profile: + # 本函数被 _generate_structs 调 54.2M 次,其中 types.py __eq__ 合计 ~30s) + # ⇒ 先做身份判定短路,等价且避免绝大多数 __eq__/str() 开销。 + if Declared is Slot: + return True if Declared == Slot or str(Declared) == str(Slot): return True _d_ptr: bool = isinstance(Declared, ir.PointerType) @@ -349,6 +354,14 @@ class StructGenMixin: return False def _generate_structs(self) -> None: + # 热路径局部化:profile 中本函数被调 35,240 次(cum 1893s),内部 + # SymbolTable.lookup 15.9M 次(16.7s)+ 真值判断触发的 __len__ 15.9M 次 + # (6.8s)⇒ 把 SymbolTable / lookup 提到局部,避免逐类重复属性查找。 + # 真值语义与 `if self.SymbolTable:` 逐字一致(SymbolTable 定义了 __len__, + # 空表为假);表在单次调用内只增不减,故提升到函数级等价。 + _symtab: Any = self.SymbolTable + _has_symtab: bool = bool(_symtab) + _sym_lookup: Any = _symtab.lookup if _symtab is not None else None all_classes: set[str] = set(self.class_methods.keys()) | set(self.class_members.keys()) preserved_structs: dict[str, ir.IdentifiedStructType] = {} @@ -367,8 +380,8 @@ class StructGenMixin: all_classes = set(self.class_methods.keys()) | set(self.class_members.keys()) for ClassName in all_classes: is_packed: bool = ClassName in self.class_packed - if self.SymbolTable: - Entry = self.SymbolTable.lookup(ClassName) + if _has_symtab and _sym_lookup is not None: + Entry = _sym_lookup(ClassName) if Entry and Entry.IsExceptionClass: continue # 注意:类名可能与 CEnum 成员名冲突(如 ASTKind.Module 枚举成员与 Module 类同名) @@ -484,8 +497,8 @@ class StructGenMixin: # Step 4: 创建最终的 structs 并设置正确的成员类型 for ClassName in all_classes: - if self.SymbolTable: - Entry = self.SymbolTable.lookup(ClassName) + if _has_symtab and _sym_lookup is not None: + Entry = _sym_lookup(ClassName) if Entry and Entry.IsExceptionClass: continue # 注意:类名可能与 CEnum 成员名冲突(如 ASTKind.Constant 枚举成员与 Constant 类同名)