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] = []
|
self.Comments: list[Token] = []
|
||||||
# 行起始字符索引表(索引 0 对应第 1 行),用于行列换算
|
# 行起始字符索引表(索引 0 对应第 1 行),用于行列换算
|
||||||
self._LineStarts: list[int] = [0]
|
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]:
|
def _PosInfo(self, pos: int) -> tuple[int, int]:
|
||||||
"""将字符索引换算为 (1-based 行号, UTF-8 字节列偏移)。
|
"""将字符索引换算为 (1-based 行号, UTF-8 字节列偏移)。
|
||||||
|
|
||||||
优化(cProfile 热点:~300 万次调用):token 顺序创建时 pos 单调
|
优化(cProfile 热点:~300 万次调用):列偏移对 ASCII 行用 len()
|
||||||
递增,用上次行索引增量顺延替代 bisect(O(log n)→摊销 O(1));
|
直接量取,避免每次 encode 分配字节串。行查找保持 bisect(C 级
|
||||||
列偏移对 ASCII 行用 len() 直接量取,避免每次 encode 分配字节串。
|
_bisect,O(log n))——增量 while 顺延实测反而更慢(Python 循环
|
||||||
|
开销 > C bisect,且 _Make 先 start 后 end 两次调用跨行时退化)。
|
||||||
"""
|
"""
|
||||||
ls: list[int] = self._LineStarts
|
idx: int = bisect.bisect_right(self._LineStarts, pos) - 1
|
||||||
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
|
|
||||||
line: int = idx + 1
|
line: int = idx + 1
|
||||||
seg: str = self.Source[ls[idx]:pos]
|
seg: str = self.Source[self._LineStarts[idx]:pos]
|
||||||
if seg.isascii():
|
if seg.isascii():
|
||||||
col_bytes: int = len(seg)
|
col_bytes: int = len(seg)
|
||||||
else:
|
else:
|
||||||
|
|||||||
Reference in new issue
Block a user