Files
snowy-yang a9bc8238ab 序列化热路径去重:to_dict 里重复求值的属性改局部复用
为什么:snapshot() 同时压在 SSE 每 250ms 推送和 full=1 动作回执两条
高频路径上,而它的成本大头是重复求值——profile 显示单次快照
1,128,001 次函数调用里近半是属性链重复计算同一份配置数据。

- Plot.to_dict:grow_days 原来经 4 个属性各求值一遍(本体 + days_left
  + is_ripe + stage),16 块地就是 64 次配置表查询。改为算一次局部
  复用;stage 的实现体拆到 _stage(grow),规则本体仍只有一份。
- Animal.to_dict:info 配置表原来查 4 次、cycle int() 两遍,改取一次。
- GameState.to_dict:weather_info 3 键 2 次查询;granary_free 原来把
  granary_capacity 和 storage_used 整个重算,改算一轮复用。

行为零变化(规则本体全在原属性里,532 项测试全绿)。
基准(tools/bench.py --repeat 5,最坏形态 16 地 + 8 牲畜):

    场景                       优化前      优化后
    engine.snapshot()          50.1 µs     44.2 µs      -12%
    session.snapshot()         51.0 µs     41.9 µs      -18%
    build_state_message()      50.9 µs     43.3 µs      -15%
    engine.available_actions   52.7 µs     48.7 µs       -8%

单次 snapshot 函数调用数 1,128,001 → 588,001(-48%),本次数字已记入
bench.py docstring 作长期参考。重复计数器全 OK(to_dict/snapshot/
net_worth 每请求仍各 1 次,无回归)。
2026-09-26 11:08:14 +08:00
..