perf(tpc): _MemberSlotAccepts 身份短路 + _generate_structs 热路径局部化(profile 第二梯队)

依据 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 次泛型特化整类发射)需要结构性改动,另行评估。
This commit is contained in:
TermiNexus committed 2026-09-29 14:41:48 +08:00
1 parent 4fc067e3bf
commit ac0d0f2cc8
1 file changed
+17 -4
+17 -4
View File
@@ -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 类同名)