From e25095da435bc30e04435da4fb0506c435a5c7ce Mon Sep 17 00:00:00 2001 From: TermiNexus Date: Mon, 17 Aug 2026 22:20:28 +0800 Subject: [PATCH] =?UTF-8?q?perf(vast):=20=5FAt=20=E5=86=85=E8=81=94=20=5FP?= =?UTF-8?q?eek(0)=20=E7=BC=93=E5=AD=98=E9=80=BB=E8=BE=91=20+=20Node=20?= =?UTF-8?q?=E6=9E=84=E9=80=A0=20=5F=5Fdict=5F=5F=20=E7=9B=B4=E5=86=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit _At 被调用 1384 万次,每次经 _Peek 再取 token;内联 _Peek(0) 缓存 (_PeekCacheIdx/_PeekCacheTok)省 2300 万次函数调用,实测单文件解析 端到端提速 ~37%。_Init 的 setattr 改 __dict__ 直写(AST 节点无 __slots__/property,行为等价)。vast 差分测试 51/53 PASS 0 FAIL。 --- lib/vast/ExprParser.py | 13 ++++++++++++- lib/vast/Nodes.py | 4 ++-- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/lib/vast/ExprParser.py b/lib/vast/ExprParser.py index b78282c..7131d15 100644 --- a/lib/vast/ExprParser.py +++ b/lib/vast/ExprParser.py @@ -77,7 +77,18 @@ class TokenStream: return self.Tokens[max(0, self.Idx - 1)] def _At(self, tok_type: str, value: str | None = None) -> bool: - tok: Token = self._Peek() + # 内联 _Peek(0) 缓存逻辑(行为与 _Peek(offset=0) 完全一致): + # 命中缓存直接取 _PeekCacheTok,miss 时读 Tokens[i] 并更新缓存; + # i >= len(Tokens) 时取末尾哨兵 token(不更新缓存)。 + i: int = self.Idx + if i >= len(self.Tokens): + tok: Token = self.Tokens[-1] + elif self._PeekCacheIdx == i: + tok = self._PeekCacheTok + else: + self._PeekCacheIdx = i + self._PeekCacheTok = self.Tokens[i] + tok = self._PeekCacheTok if tok.Type != tok_type: return False if value is not None and tok.Value != value: diff --git a/lib/vast/Nodes.py b/lib/vast/Nodes.py index a8aa790..8d8c498 100644 --- a/lib/vast/Nodes.py +++ b/lib/vast/Nodes.py @@ -310,9 +310,9 @@ def _MakeNodeClass(name: str, fields: tuple[str, ...], attrs: tuple[str, ...]) - f'{name} constructor takes at most {len(fields)} positional arguments' ) for fname, val in zip(fields, args): - setattr(self, fname, val) + self.__dict__[fname] = val for k, v in kwargs.items(): - setattr(self, k, v) + self.__dict__[k] = v base_name: str | None = _BASE_CLASS.get(name) base_cls: type = globals()[base_name] if base_name else AST