From 4641777db121d4961e84cc4fdec9a12aee514bb5 Mon Sep 17 00:00:00 2001 From: TermiNexus Date: Wed, 30 Sep 2026 23:18:29 +0800 Subject: [PATCH] =?UTF-8?q?perf(Phase2Translator/=5Fsplit=5Fll):=20?= =?UTF-8?q?=E6=8B=AC=E5=8F=B7=E8=AE=A1=E6=95=B0=E8=B5=B0=20C=20=E7=BA=A7?= =?UTF-8?q?=20str.count=20=E5=BF=AB=E8=B7=AF=E5=BE=84=20+=20=E8=B0=83?= =?UTF-8?q?=E7=94=A8=E7=82=B9=E9=A2=84=E7=AD=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit prof 基线(PROF/20260930_224857,主进程 433.69s)实测 _split_ll: ncalls 53 / tottime 0.263s / cumtime 3.347s,其中 _count_braces_outside_strings 102,397 次 / tottime 1.999s / cumtime 2.769s (占其 cumtime 的 83%);同函数内 strip 0.078s、startswith 0.084s 可忽略。 - _count_braces_outside_strings:行内不含 c" 时退化为 C 级 str.count('{') - str.count('}'),不再逐字符跑 Python 循环。 语义逐字等价:逐字符版唯一的额外分支就是"跳过 c" 字面量",而该分支 只在出现子串 c" 时进入 ⇒ 无 c" 时等于纯括号计数。 - 两个调用点(in_define 函数体续行 / in_global_def 全局初始化器续行)加预筛 `'{' in line or '}' in line`:无花括号的行必然返回 0,省掉一次函数调用。 - `stripped == '{'` 分支的 3 处 re.sub 字面量改用同模式串的预编译常量 (_RE_DEFINE_PREFIX / _RE_DEFINE_LINKAGE / _RE_ALWAYSINLINE),与上面 define 分支保持同一口径(模式串一字未改)。 顺带实测(供下一步参考):str.strip 179M 次 / 22.8s 是全流程最大项,但 cProfile 归属帧几乎全在 stdlib(re.match 5.25M、threading.wait 4.88M、 futures.as_completed 3.63M、json.load 0.66M、subprocess 各 ~0.4M); 本项目内只有 _extract_llvm_type_name 1.37M、_ParseDwarfLineRows 0.34M、 _split_ll 0.35M。 --- lib/Projectrans/Phase2Translator.py | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/lib/Projectrans/Phase2Translator.py b/lib/Projectrans/Phase2Translator.py index 203c58f..4856850 100644 --- a/lib/Projectrans/Phase2Translator.py +++ b/lib/Projectrans/Phase2Translator.py @@ -922,7 +922,16 @@ def _PyiCacheWorkerInitializer(temp_dir: str) -> None: def _count_braces_outside_strings(text: str) -> int: - """统计花括号差值,跳过 c"..." 字符串字面量内部的括号""" + """统计花括号差值,跳过 c"..." 字符串字面量内部的括号 + + 快路径(prof 基线:本函数 102,397 次调用 / self 2.0s,占 _split_ll cumtime + 3.35s 的 83%,是全流程 str.strip 之后第二大的"纯 Python 逐字符"热点): + 行内不含 `c"` 时,"跳过字符串内部括号"这一语义退化为"整行括号计数", + 直接用 C 级 str.count 一次算完。含 `c"` 的行(主要见于 c"..." 全局串常量) + 仍走下面的逐字符扫描,语义逐字不变。 + """ + if 'c"' not in text: + return text.count('{') - text.count('}') count = 0 i = 0 while i < len(text): @@ -1720,7 +1729,9 @@ class Phase2Translator: if in_global_def: text_lines.append(line) global_type_parts.append(line.strip()) - global_brace_depth += _count_braces_outside_strings(line) + # 预筛:无花括号的行必然贡献 0(与计数器返回值逐字等价,见其快路径) + if '{' in line or '}' in line: + global_brace_depth += _count_braces_outside_strings(line) if global_brace_depth <= 0: full_type = ' '.join(global_type_parts).strip() depth = 0 @@ -1744,7 +1755,10 @@ class Phase2Translator: if in_define: text_lines.append(line) - brace_depth += _count_braces_outside_strings(line) + # 预筛:函数体指令行绝大多数不含花括号,跳过即省掉一次函数调用 + # (prof:本函数 102k 次调用;有花括号的行仍按原语义计数) + if '{' in line or '}' in line: + brace_depth += _count_braces_outside_strings(line) if brace_depth <= 0: in_define = False continue @@ -1770,9 +1784,11 @@ class Phase2Translator: brace_depth = 1 in_define = True if prev_stripped.startswith('define '): - decl_line = re.sub(r'^define\s+', 'declare ', prev_stripped) - decl_line = re.sub(r'\b(linkonce_odr|weak_odr|linkonce|weak|common|appending|internal|private)\s+', '', decl_line) - decl_line = re.sub(r'\balwaysinline\s+', '', decl_line) + # 与上面 define 分支同一组预编译正则(模式串一字未改), + # 避免 re 模块级的"模式串哈希→缓存查找"逐行开销 + decl_line = _RE_DEFINE_PREFIX.sub('declare ', prev_stripped) + decl_line = _RE_DEFINE_LINKAGE.sub('', decl_line) + decl_line = _RE_ALWAYSINLINE.sub('', decl_line) paren_pos = decl_line.rfind(')') if paren_pos >= 0: decl_line = decl_line[:paren_pos + 1]