perf(vast): 回滚 _PosInfo 增量行查找(Python while 慢于 C bisect)
新 cProfile(232s)显示 _PosInfo tottime 1.74s→2.84s:增量 while 顺延的 Python 循环开销大于 _bisect(C 级 O(log n)),且 _Make 先 start 后 end 两次调用跨行时退化。回滚为 bisect + 保留 isascii 快速路径(避免 encode 分配)。
This commit is contained in:
1 parent
08e7b8d0c0
commit
2dbf348329
1 file changed
+6
-17
+6
-17
@@ -131,9 +131,6 @@ class Tokenizer:
|
||||
self.Comments: list[Token] = []
|
||||
# 行起始字符索引表(索引 0 对应第 1 行),用于行列换算
|
||||
self._LineStarts: list[int] = [0]
|
||||
# _PosInfo 增量缓存:token 顺序创建时 pos 单调递增,免 bisect
|
||||
self._LastLineIdx: int = 0
|
||||
self._LastPos: int = -1
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# 位置换算
|
||||
@@ -141,22 +138,14 @@ class Tokenizer:
|
||||
def _PosInfo(self, pos: int) -> tuple[int, int]:
|
||||
"""将字符索引换算为 (1-based 行号, UTF-8 字节列偏移)。
|
||||
|
||||
优化(cProfile 热点:~300 万次调用):token 顺序创建时 pos 单调
|
||||
递增,用上次行索引增量顺延替代 bisect(O(log n)→摊销 O(1));
|
||||
列偏移对 ASCII 行用 len() 直接量取,避免每次 encode 分配字节串。
|
||||
优化(cProfile 热点:~300 万次调用):列偏移对 ASCII 行用 len()
|
||||
直接量取,避免每次 encode 分配字节串。行查找保持 bisect(C 级
|
||||
_bisect,O(log n))——增量 while 顺延实测反而更慢(Python 循环
|
||||
开销 > C bisect,且 _Make 先 start 后 end 两次调用跨行时退化)。
|
||||
"""
|
||||
ls: list[int] = self._LineStarts
|
||||
if pos >= self._LastPos and self._LastLineIdx + 1 < len(ls):
|
||||
idx: int = self._LastLineIdx
|
||||
nls: int = len(ls)
|
||||
while idx + 1 < nls and ls[idx + 1] <= pos:
|
||||
idx += 1
|
||||
else:
|
||||
idx = bisect.bisect_right(ls, pos) - 1
|
||||
self._LastLineIdx = idx
|
||||
self._LastPos = pos
|
||||
idx: int = bisect.bisect_right(self._LineStarts, pos) - 1
|
||||
line: int = idx + 1
|
||||
seg: str = self.Source[ls[idx]:pos]
|
||||
seg: str = self.Source[self._LineStarts[idx]:pos]
|
||||
if seg.isascii():
|
||||
col_bytes: int = len(seg)
|
||||
else:
|
||||
|
||||
Reference in new issue
Block a user