Files
TankIC/3DTank/tools/analyze_enum_trace.py

72 lines
2.7 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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())