perf(tpc): import 热路径优化——walk 结果缓存 + DebugPrint 参数惰性化
- import 兜底查找(_EmitModuleDeclarationsLlvm)每次解析失败都 os.walk 递归扫描 includes/工程目录,且多级模块名与 basename 永不匹配纯浪费:改为多级跳过 + 目录 walk 结果类级缓存(编译进程内目录不变) - DebugPrint 调用点(HandlesTypeMerge 类型查询热路径)无条件构造 f-string 参数(含昂贵的 ast.dump),即使 DebugFile 未设置也执行:改为 getattr(DebugFile) 防护后才构造(单文件 profile:_io.open 1253 次 1.76s + DebugPrint cum 2.24s)
This commit is contained in:
1 parent
daf79af1cc
commit
c62153a685
2 files changed
+27
-11
No files matched your search
@@ -22,6 +22,10 @@ class ImportHandle(BaseHandle):
|
||||
_pyi_cache = {}
|
||||
_pyi_cache_dir = None
|
||||
_project_root_cache = None
|
||||
# 目录 os.walk 结果缓存(import 失败兜底查找用):目录 -> [(root, files)]。
|
||||
# 编译进程内 SearchDirsForSubmodule(includes/LibraryPaths/工程目录)内容不变,
|
||||
# 避免每次 import 解析失败都全量递归扫描目录树(PROF:import 热路径高频调用)。
|
||||
_walk_cache: dict[str, list[tuple[str, list[str]]]] = {}
|
||||
# 类级 stub 索引:class_name -> list of (full_name, struct_body, file_sha1, from_output)
|
||||
# 一次扫描所有 .stub.ll 文件构建索引,避免 _TryLoadStructFromStub 每次调用都全量扫描
|
||||
# (原 609 次调用 × ~100 stub 文件 × ~50 行 = 5.5M 正则匹配 → 一次扫描 ~5000 匹配)
|
||||
@@ -647,18 +651,27 @@ class ImportHandle(BaseHandle):
|
||||
SearchFromDirs = [os.getcwd()]
|
||||
SearchDirsForSubmodule = SearchFromDirs + [os.path.join(TransPyCRoot, 'includes'), os.path.join(TransPyCRoot, 'lib', 'includes')] + list(self.Trans.LibraryPaths)
|
||||
for SearchPath in SearchDirsForSubmodule:
|
||||
if os.path.isdir(SearchPath):
|
||||
for root, dirs, files in os.walk(SearchPath):
|
||||
if '__pycache__' in root:
|
||||
continue
|
||||
for src_ext in ('.vp', '.py', '.vpi', '.pyi'):
|
||||
if module_name + src_ext in files:
|
||||
FullModulePath = os.path.join(root, module_name + src_ext)
|
||||
break
|
||||
if FullModulePath:
|
||||
if not os.path.isdir(SearchPath):
|
||||
continue
|
||||
# 多级模块名(含 '.')与 basename 文件列表(files 无路径)
|
||||
# 永不匹配 `module_name + ext in files`,walk 纯属浪费,跳过。
|
||||
if '.' in module_name:
|
||||
continue
|
||||
# 目录 walk 结果缓存(编译进程内目录内容不变):import 热路径
|
||||
# 高频解析失败时避免重复递归扫描 includes/工程目录(PROF 热点)
|
||||
walk_entries: list[tuple[str, list[str]]] = ImportHandle._walk_cache.get(SearchPath)
|
||||
if walk_entries is None:
|
||||
walk_entries = [(r, fs) for r, dirs, fs in os.walk(SearchPath) if '__pycache__' not in r]
|
||||
ImportHandle._walk_cache[SearchPath] = walk_entries
|
||||
for root, files in walk_entries:
|
||||
for src_ext in ('.vp', '.py', '.vpi', '.pyi'):
|
||||
if module_name + src_ext in files:
|
||||
FullModulePath = os.path.join(root, module_name + src_ext)
|
||||
break
|
||||
if FullModulePath:
|
||||
break
|
||||
if FullModulePath:
|
||||
break
|
||||
# fail-fast:模块在所有来源都"完全未知"时立即报错,暴露 import 路径错误
|
||||
# (如目录重组后未更新的旧路径)。之前静默容忍导致引用方跨模块 mangled
|
||||
# 前缀 fallback 当前模块 sha1,链接期才暴露 undefined symbol。
|
||||
|
||||
@@ -37,7 +37,9 @@ class HandlesTypeMerge(BaseHandle):
|
||||
"""鍐呴儴鏂规硶锛岃繑鍥?CTypeInfo"""
|
||||
LineNum = getattr(Node, 'lineno', None)
|
||||
|
||||
self.Trans.DebugPrint(f"[GetCTypeInfo] Node type: {type(Node).__name__}, dump: {ast.dump(Node)[:60]}...")
|
||||
if getattr(self.Trans, 'DebugFile', None):
|
||||
# 仅 debug 模式构造参数(ast.dump 昂贵,非 debug 时无条件执行是隐藏热点)
|
||||
self.Trans.DebugPrint(f"[GetCTypeInfo] Node type: {type(Node).__name__}, dump: {ast.dump(Node)[:60]}...")
|
||||
|
||||
if isinstance(Node, ast.Constant):
|
||||
TypeName = Node.value
|
||||
@@ -152,7 +154,8 @@ class HandlesTypeMerge(BaseHandle):
|
||||
if resolved:
|
||||
ModulePath = resolved
|
||||
|
||||
self.Trans.DebugPrint(f"[GetCTypeInfo-Attribute] 查询: '{TypeName}' ModulePath: {ModulePath}")
|
||||
if getattr(self.Trans, 'DebugFile', None):
|
||||
self.Trans.DebugPrint(f"[GetCTypeInfo-Attribute] 查询: '{TypeName}' ModulePath: {ModulePath}")
|
||||
|
||||
if ModulePath == 't' and TypeName == 'State':
|
||||
Info = CTypeInfo()
|
||||
|
||||
Reference in new issue
Block a user