feat(tpc): PROF 输出按编译启动时间分目录,不再清理旧目录
需求(2026-09-29):PROF 按启动时间分组新建文件夹生成,不清理旧的 PROF。
改动:
- Phase2Translator:新增 `StartProfRun()`(在 PROF 根目录下按 `YYYYmmdd_HHMMSS`
新建本次编译专属子目录,同名补 `_N`;失败回落 PROF 根目录)与
`GetProfRunDir()`(主进程用已选定目录,worker 用继承的环境变量
`TPC_PROF_RUN_DIR` 复用同一目录)。原 `_CleanProfFiles()` 删除——它的语义
是"每次编译删掉 PROF 下全部 *.prof",与"保留历次"直接冲突。
- worker_prof_*.prof 落 `PROF/<启动时间>/`。
- main_prof_{pid}.prof 与 main_time.txt 同样落该目录(Projectrans.py)。
- Config.main 启动时调用 StartProfRun 并打印本次输出目录。
子目录名经环境变量传子进程:ProcessPoolExecutor 用 spawn 起新解释器,进程内
模块态不共享,环境变量随进程继承 ⇒ 同一次编译的所有 worker 落在同一目录,
不会各建各的。
This commit is contained in:
1 parent
467e62a45e
commit
030d0fd149
3 files changed
+66
-26
No files matched your search
@@ -588,27 +588,65 @@ def _parallel_translate_batch(batch: list, src_root: str, temp_dir: str, output_
|
||||
# 子进程性能剖析:主进程 cProfile 只能看到进程池等待(WaitForMultipleObjects/
|
||||
# as_completed),看不到 worker 进程内部 CPU 分布(vast parse 等热点)。
|
||||
# 固定启用(不设环境变量开关),worker 每个任务导出 cProfile dump
|
||||
# (worker_prof_{pid}_{seq}.prof)到 PROF_DIR(D:\Users\TermiNexus\Desktop\TransPyC\PROF),
|
||||
# 可用 pstats 合并分析。每次编译开始时由 _CleanProfFiles 清理该目录 *.prof。
|
||||
# (worker_prof_{pid}_{seq}.prof),主进程导出 main_prof_{pid}.prof + main_time.txt。
|
||||
# 输出落在 PROF_DIR/<启动时间>/ 下的**本次编译专属目录**(2026-09-29 起)。
|
||||
# ==================================================================
|
||||
import functools as _functools
|
||||
import time as _time
|
||||
|
||||
# 硬编码 PROF 输出目录(2026-08-18 起不再用 TPC_WORKER_PROF 环境变量控制)
|
||||
# 硬编码 PROF 根目录(2026-08-18 起不再用 TPC_WORKER_PROF 环境变量控制)
|
||||
PROF_DIR: str = r'D:\Users\TermiNexus\Desktop\TransPyC\PROF'
|
||||
|
||||
# 本次编译的 run 目录:按启动时间在 PROF_DIR 下新建子目录,**不清理旧目录**
|
||||
# (2026-09-29 用户要求保留历次 profile 以便跨次对比,旧行为是每次编译删掉
|
||||
# PROF 根目录下全部 *.prof ⇒ 只能看最近一次)。
|
||||
# 子目录名经环境变量传给 worker:ProcessPoolExecutor 用 spawn 起新解释器,
|
||||
# 进程内模块态不共享;环境变量随子进程继承 ⇒ 同一次编译的所有 worker 落在
|
||||
# 同一个 run 目录,不会各建各的目录。
|
||||
_PROF_RUN_ENV: str = 'TPC_PROF_RUN_DIR'
|
||||
_prof_run_dir: str | None = None
|
||||
|
||||
def _CleanProfFiles() -> None:
|
||||
"""清理 PROF_DIR 下全部 *.prof(每次编译开始调用)。"""
|
||||
|
||||
def StartProfRun() -> str:
|
||||
"""每次编译开始时调用一次:创建本次编译专属的 PROF 子目录,返回其路径。
|
||||
|
||||
目录名 = PROF 根目录下 `YYYYmmdd_HHMMSS`(编译启动时刻);同名(同一秒内
|
||||
二次启动)补 `_N` 序号。创建失败时回落到 PROF 根目录,保证不因 profiling
|
||||
影响编译本身。成功后把目录写进环境变量,供 worker 子进程复用。
|
||||
"""
|
||||
global _prof_run_dir
|
||||
if _prof_run_dir:
|
||||
return _prof_run_dir
|
||||
_name: str = _time.strftime('%Y%m%d_%H%M%S')
|
||||
_dir: str = os.path.join(PROF_DIR, _name)
|
||||
_seq: int = 1
|
||||
while os.path.isdir(_dir):
|
||||
_seq += 1
|
||||
_dir = os.path.join(PROF_DIR, f'{_name}_{_seq}')
|
||||
try:
|
||||
if os.path.isdir(PROF_DIR):
|
||||
for _n in os.listdir(PROF_DIR):
|
||||
if _n.endswith('.prof'):
|
||||
try:
|
||||
os.remove(os.path.join(PROF_DIR, _n))
|
||||
except OSError:
|
||||
pass
|
||||
os.makedirs(_dir, exist_ok=True)
|
||||
except OSError:
|
||||
pass
|
||||
return PROF_DIR
|
||||
_prof_run_dir = _dir
|
||||
os.environ[_PROF_RUN_ENV] = _dir
|
||||
return _dir
|
||||
|
||||
|
||||
def GetProfRunDir() -> str:
|
||||
"""当前进程写 profile 应落的目录。
|
||||
|
||||
主进程 = StartProfRun 选定的 run 目录;worker = 继承来的环境变量指向的目录。
|
||||
两者都取不到(未先调 StartProfRun,如 worker 被单独拉起)时回落到 PROF 根目录,
|
||||
宁可文件落在根目录也不丢 dump。
|
||||
"""
|
||||
global _prof_run_dir
|
||||
if _prof_run_dir:
|
||||
return _prof_run_dir
|
||||
_env_dir: str = os.environ.get(_PROF_RUN_ENV, '')
|
||||
if _env_dir:
|
||||
_prof_run_dir = _env_dir
|
||||
return _env_dir
|
||||
return PROF_DIR
|
||||
|
||||
|
||||
def _ProfileWorker(_fn):
|
||||
@@ -635,9 +673,10 @@ def _ProfileWorker(_fn):
|
||||
_seq: int = getattr(_wrapper, '_seq', 0) + 1
|
||||
_wrapper._seq = _seq
|
||||
try:
|
||||
if not os.path.isdir(PROF_DIR):
|
||||
os.makedirs(PROF_DIR, exist_ok=True)
|
||||
_out: str = os.path.join(PROF_DIR, f'worker_prof_{os.getpid()}_{_seq}.prof')
|
||||
_out_dir: str = GetProfRunDir()
|
||||
if not os.path.isdir(_out_dir):
|
||||
os.makedirs(_out_dir, exist_ok=True)
|
||||
_out: str = os.path.join(_out_dir, f'worker_prof_{os.getpid()}_{_seq}.prof')
|
||||
_prof.dump_stats(_out)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
Reference in new issue
Block a user