72 lines
2.7 KiB
Python
72 lines
2.7 KiB
Python
# analyze_enum_trace.py - 分析客户端「枚举读取」打点:确认读 enum 时字节游标是否推进
|
||
#
|
||
# 数据来源:镜像站 module_24635.js 的 Kt.t7h 补丁(枚举读器)。它记录
|
||
# {enum: 枚举 kClass 名, pos0/pos1: 读前/读后的字节游标, bit: nullmap 位游标}
|
||
# 节流 POST 到 serve.js 的 /__dump__/enum_trace.json。
|
||
#
|
||
# 判读:
|
||
# pos1 - pos0 == 0 → 该枚举不占字节(与源码 EnumCodecInfo/Kt 空实现一致);
|
||
# pos1 - pos0 != 0 → 客户端确实为这个枚举读了字节,说明宽度不是常量。
|
||
#
|
||
# 用法: python tools/analyze_enum_trace.py [--names names]
|
||
import json
|
||
import os
|
||
import sys
|
||
from collections import Counter, defaultdict
|
||
|
||
Root = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||
|
||
|
||
def Arg(Name, Def):
|
||
if '--' + Name in sys.argv:
|
||
I = sys.argv.index('--' + Name)
|
||
if I + 1 < len(sys.argv):
|
||
return sys.argv[I + 1]
|
||
return Def
|
||
|
||
|
||
NamesDir = os.path.abspath(Arg('names', os.path.join(Root, 'names')))
|
||
TracePath = os.path.join(NamesDir, 'enum_trace.json')
|
||
FieldsPath = os.path.join(NamesDir, 'codec_fields.json')
|
||
|
||
|
||
def Main():
|
||
if not os.path.exists(TracePath):
|
||
print('缺少 ' + TracePath)
|
||
print('请先用镜像站进一局战斗(Kt.t7h 已打枚举打点,会自动 POST)。')
|
||
return 1
|
||
with open(TracePath, 'r', encoding='utf-8') as F:
|
||
Data = json.load(F)
|
||
Rows = Data.get('trace') or []
|
||
print('枚举打点:%d 条(采集于 %s)' % (len(Rows), Data.get('at', '?')))
|
||
|
||
with open(FieldsPath, 'r', encoding='utf-8') as F:
|
||
Codecs = json.load(F).get('Codecs') or {}
|
||
# 枚举类型名 → 用到它的 (codec, 字段)
|
||
Users = defaultdict(list)
|
||
for Key, C in Codecs.items():
|
||
for F in C.get('Fields') or []:
|
||
T = str(F.get('Type') or '')
|
||
if T.startswith('enum<') and T.endswith('>'):
|
||
Users[T[5:-1]].append((Key, F.get('Name')))
|
||
|
||
Delta = Counter()
|
||
ByEnum = defaultdict(Counter)
|
||
for R in Rows:
|
||
D = (R.get('pos1', -1) - R.get('pos0', -1)) if R.get('pos0', -1) >= 0 else -1
|
||
Delta[D] += 1
|
||
ByEnum[R.get('enum') or '?'][D] += 1
|
||
|
||
print(' 字节推进量分布(pos1-pos0):%s' % dict(Delta))
|
||
print(' 按枚举类型:')
|
||
for Name, Cnt in sorted(ByEnum.items(), key=lambda X: -sum(X[1].values()))[:25]:
|
||
Where = Users.get(Name) or []
|
||
Sample = ('%s.%s' % Where[0]) if Where else '?'
|
||
print(' %-4s 次数=%-5d 推进=%s 使用处=%s%s'
|
||
% (Name or '?', sum(Cnt.values()), dict(Cnt), Sample, (' 等 %d 处' % len(Where)) if len(Where) > 1 else ''))
|
||
return 0
|
||
|
||
|
||
if __name__ == '__main__':
|
||
sys.exit(Main())
|