15.1 指标的定义与口径

全卷七条代理指标第一次被收成一张总表:分支覆盖率、结局分布熵、张力曲线 MAE、好感度曲线 MAE、一致性残差、节奏密度偏差、整数不变量残差,每条给全定义、量纲、真源字段、实测值与首见小节。脚本从规格重算六条并与各章产物逐条对账,落 out/nm_15_1_metric_catalog.json。

《游戏设计》卷一《玩法机制与可执行规格》 那一套给的是玩法规格的度量口径;本章给的是叙事规格的度量口径——指标集不同(那边是一局的动力学,这边是整张故事图的路径形状),但「整数化 + 确定性 + 只做相对比较」的纪律同源。第 15 章是全卷的总表章:前十四章把指标一条条立起来,这一章把它们收进同一张表,并写清每条指标不能声称什么。

15.1 指标的定义与口径

《雾港夜航》从头到尾只被七个整数描述,可它们散在十四个章节里:2.2 立覆盖率、3.1 立熵、5.2 立张力 MAE、7.2 立密度、9.1 立残差、8.1 立好感度曲线,1.1 立整数不变量。散着放有个隐患——同一件事在不同章节容易被讲成不同口径,读的人凑不齐一张全景。本节把七条指标收进同一张表,每条给全五样东西:定义、量纲、真源字段、实测值、首见小节。

一张定义表要回答的五个问题

字段回答的问题
definition这个数怎么算(分母口径、取整规则)
unit量纲是什么(千分 / 毫比特 / 毫 / 计数)
truth_source读的是哪段真源(规格里的哪个字段)
observed当前实测是多少(脚本实跑填入)
first_section第一次在哪一节立起来(可回溯)

前四项决定「这个数能被算出来」,第五项决定「这个数能被追溯」。缺任何一项,这张表就退化成一份数字清单——数字对不上时,没人知道该回去改哪一节。

七条指标总表

#指标量纲实测阈值首见
1分支覆盖率千分446≥ 850§2.2
2结局分布熵毫比特1714≥ 1500§3.1
3张力曲线 MAE毫0≤ 1000§5.2
4好感度曲线 MAE毫5739≤ 12000§15.1
5一致性残差计数8= 0§9.1
6节奏密度偏差千分5= 0§7.2
7整数不变量残差计数0= 0§1.1

七条里只有第 7 条是恒等判据(必须为 0,无容差),其余六条都是阈值判据(越过阈值才判得动方向)。而七条无一例外都是 proxy——度量的都是规格里的结构量,没有一条碰得到玩家。

好感度曲线 MAE:本节首次给出定义

第 4 条是全卷唯一一条本节才首次给出定义的指标,原因值得说清:真源 config/story_spec.json 里有 metrics.affinity_mae_max = 12 这个阈值,却没有对应的 target_affinity_curve 字段——阈值摆在那里,却没有可比的目标曲线。这是一处规格欠声明。

本节按「路径对采样基线」把它定义死:取确定性路径(每步走第一个可用选项)的四条好感度曲线,与随机策略 2000 条采样的逐步均值曲线逐变量、逐步相减,sum(|确定性 − 均值|) × 1000 // 比较步数,单位毫(1 点 = 1000 毫,与张力 MAE 同口径)。实测 5739 毫,落在 12000 毫阈值内。这不是「关系写得好」的证明,只是「这条具体路径偏离总体基线多远」的读数。

S 层:从真源重算并对账

脚本 sim/nm_15_1_metric_catalog.py 不抄各章产物,而是从 config/story_spec.json 重算六条指标(分支覆盖率、结局分布熵、张力曲线 MAE、好感度曲线 MAE、一致性静态残差、整数不变量残差),只有「节奏密度偏差」读第 7 章产物(信息事件口径属于 7.2,本节不重复实现):

#!/usr/bin/env python3
# file: sim/nm_15_1_metric_catalog.py
# tier: S
# verify: /opt/homebrew/bin/python3 sim/nm_15_1_metric_catalog.py
"""卷三 15.1 指标的定义与口径(S 层):全卷代理指标总表。

把散落全卷的七条 proxy 指标收成一张表,每条给出精确定义、量纲、真源字段、实测值
与首见小节。六条从 config/story_spec.json **重算**,再与各章产物逐条对账;只有
「节奏密度偏差」读第 7 章产物(信息事件口径属于 7.2)。好感度曲线 MAE 是全卷唯一
一条本节首次给出定义的指标:真源里只有阈值没有目标曲线字段。全部整数、全部 proxy。
产出 out/nm_15_1_metric_catalog.json。
"""
from __future__ import annotations

import json
import math
import os
import sys

import nm_15_common as c

N_ENTROPY, N_MEAN, N_COVER = 20000, 2000, 200


def main() -> int:
    spec = c.load_json("config/story_spec.json")
    by = {n["id"]: n for n in spec["dialogue"]}
    vars_ = sorted(spec["state"]["vars"])
    m, beats = spec["metrics"], spec["beats"]

    # [1] 分支覆盖率:确定性路径 vs 采样 200 条(去重边口径,分母 56)
    e_dedup = len(c.edges_of(spec))
    _, det_nodes, det_trail, det_curves, _, bad_det = c.walk(spec, None)
    det_edges = c.det_edges(spec)
    cov_det = len(det_edges) * 1000 // e_dedup
    rng, seen = c.SEED, set()
    for _ in range(N_COVER):
        _, nd, _, _, rng, _ = c.walk(spec, rng, 0)
        seen |= {(nd[i], nd[i + 1]) for i in range(len(nd) - 1)}
    cov_rand = len(seen) * 1000 // e_dedup

    # [2] 结局分布熵:采样 20000 条
    rng, dist = c.SEED, {}
    for _ in range(N_ENTROPY):
        end, _, _, _, rng, _ = c.walk(spec, rng, 0)
        key = by[end].get("ending", "(未终局)")
        dist[key] = dist.get(key, 0) + 1
    ent_sampled = c.entropy_milli_bits(list(dist.values()), N_ENTROPY)

    # [3] 张力曲线 MAE:路径 11 拍 / 全量 16 拍
    visited = {by[nid]["scene"] for nid in det_nodes}
    idx = [i for i, b in enumerate(beats) if b["scene"] in visited]
    curve = [beats[i]["tension"] for i in idx]
    mae_path = sum(abs(beats[i]["tension"] - m["target_tension_curve"][i]) for i in idx) * 1000 // len(idx)
    all_t = [b["tension"] for b in beats]
    mae_all = sum(abs(a - b) for a, b in zip(all_t, m["target_tension_curve"])) * 1000 // len(all_t)

    # [4] 好感度曲线 MAE:确定性曲线 vs 随机策略均值曲线(本节首次定义)
    rand_mean, bad_rand = c.mean_curve(spec, N_MEAN, 0, c.SEED)
    num = cnt = 0
    for v in vars_:
        for i in range(min(len(det_curves[v]), len(rand_mean[v]))):
            num += abs(det_curves[v][i] - rand_mean[v][i])
            cnt += 1
    aff_mae = num * 1000 // cnt

    # [5] 一致性静态残差
    d, k, s_, r = c.static_residual(spec)
    residual = len(d) + k + s_ + r

    # [6] 节奏密度偏差:读第 7 章产物(信息事件口径属于 7.2)
    dens = c.load_json("out/nm_07_2_density.json")
    dens_dev = dens["dry_share_permille"] + dens["burst_share_permille"]

    # [7] 整数不变量残差:恒 0
    inv = bad_det + bad_rand + sum(1 for t in all_t if not 1 <= t <= 5)
    inv += sum(1 for n in spec["dialogue"] for ch in (n.get("choices") or [])
               for v in ((ch.get("effects") or {}).get("set") or {}).values() if v not in (0, 1))
    inv += 0 if len(det_nodes) == len(det_trail) + 1 else 1

    rows = [
        {"id": 1, "metric": "branch_coverage", "name": "分支覆盖率", "unit": "permille", "unit_cn": "千分",
         "observed": cov_det, "threshold": m["coverage_target_permille"], "first_section": "2.2"},
        {"id": 2, "metric": "ending_entropy", "name": "结局分布熵", "unit": "milli_bits", "unit_cn": "毫比特",
         "observed": ent_sampled, "threshold": m["ending_entropy_min_milli_bits"], "first_section": "3.1"},
        {"id": 3, "metric": "tension_curve_mae", "name": "张力曲线 MAE", "unit": "milli", "unit_cn": "毫",
         "observed": mae_path, "threshold": m["tension_mae_max"] * 1000, "first_section": "5.2"},
        {"id": 4, "metric": "affinity_curve_mae", "name": "好感度曲线 MAE", "unit": "milli", "unit_cn": "毫",
         "observed": aff_mae, "threshold": m["affinity_mae_max"] * 1000, "first_section": "15.1"},
        {"id": 5, "metric": "consistency_residual", "name": "一致性残差", "unit": "count", "unit_cn": "计数",
         "observed": residual, "threshold": 0, "first_section": "9.1"},
        {"id": 6, "metric": "density_deviation", "name": "节奏密度偏差", "unit": "permille", "unit_cn": "千分",
         "observed": dens_dev, "threshold": 0, "first_section": "7.2"},
        {"id": 7, "metric": "invariant_residual", "name": "整数不变量残差", "unit": "count", "unit_cn": "计数",
         "observed": inv, "threshold": 0, "first_section": "1.1"},
    ]

    print(f"spec={spec['meta']['title']}  节拍 {len(beats)}(tension 和 {sum(all_t)})"
          f"  对话节点 {len(spec['dialogue'])}  去重边 {e_dedup}  结局 {len(spec['endings'])}")
    print("全卷代理指标总表(seed=20261016,本机实跑,全部整数,全部 proxy)")
    for r_ in rows:
        print(f"   {r_['id']}  {r_['name']} = {r_['observed']} {r_['unit_cn']}"
              f"(阈值 {r_['threshold']},首见 §{r_['first_section']})")
    print(f"   分支覆盖率对照:确定性路径 {len(det_edges)}/{e_dedup} = {cov_det}‰;"
          f"采样 {N_COVER} 条 {len(seen)}/{e_dedup} = {cov_rand}‰")
    print(f"   结局分布熵:采样 {N_ENTROPY} 条 {dist}")
    print(f"   好感度曲线 MAE:确定性曲线 vs 随机 {N_MEAN} 条均值曲线,{cnt} 个逐步比较,差和 {num} 点")
    print(f"   一致性残差:D {len(d)} + K {k} + S {s_} + R {r} = {residual}")

    # 对账:本节重算值 vs 各章产物
    checks = [
        ("覆盖率 2.2", cov_det, c.load_json("out/nm_02_2_coverage.json")["sources"][0]["dedup_permille"]),
        ("熵 3.1", ent_sampled, c.load_json("out/nm_03_1_ending_entropy.json")["entropy_sampled_milli_bits"]),
        ("张力 MAE 6.2 路径", mae_path, c.load_json("out/nm_06_2_mae.json")["mae_path_milli"]),
        ("张力 MAE 6.2 全量", mae_all, c.load_json("out/nm_06_2_mae.json")["mae_all_milli"]),
        ("一致性残差 9.1", residual, c.load_json("out/nm_09_1_residual.json")["static_total"]),
        ("密度偏差 7.2", dens_dev, dens["dry_share_permille"] + dens["burst_share_permille"]),
    ]
    print("对账(本节重算值 = 各章产物):")
    for label, mine, theirs in checks:
        print(f"   {label}  本节 {mine}  产物 {theirs}  {'OK' if mine == theirs else 'MISMATCH'}")
        assert mine == theirs, f"{label} 对账不一致:{mine} != {theirs}"
    prod81 = c.load_json("out/nm_08_1_affinity_curve.json")
    det_ok = all(prod81["deterministic"]["curves"][v]["curve"] == det_curves[v] for v in vars_)
    print(f"   好感度曲线 8.1     确定性 4 条曲线逐项一致 {det_ok}")
    assert det_ok, "好感度曲线与 8.1 产物不一致"

    # 定义表 lint(D 层)
    entries = c.load_json("config/nm_15_1_metric_definition_table.json")["metrics"]
    need = ["id", "metric", "name", "kind", "unit", "definition", "truth_source", "measures",
            "does_not_measure", "allowed_use", "first_section", "threshold_field"]
    miss = [(e.get("metric"), f) for e in entries for f in need if f not in e]
    bad_kind = [e["metric"] for e in entries if e.get("kind") != "proxy"]
    empty = [e["metric"] for e in entries if not e.get("does_not_measure") or not e.get("allowed_use")]
    by_id = {e["id"]: e for e in entries}
    drift = [r_["name"] for r_ in rows if by_id[r_["id"]]["unit"] != r_["unit"]
             or by_id[r_["id"]]["name"] != r_["name"]
             or by_id[r_["id"]]["first_section"] != r_["first_section"]]
    print(f"定义表 lint     条目 {len(entries)} / 缺字段 {len(miss)} / 非 proxy {len(bad_kind)}"
          f" / 空清单 {len(empty)} / 口径漂移 {len(drift)}")
    assert len(entries) == len(rows) and not (miss or bad_kind or empty or drift), "定义表 lint 失败"

    os.makedirs(c.OUT, exist_ok=True)
    with open(os.path.join(c.OUT, "nm_15_1_metric_catalog.json"), "w", encoding="utf-8") as fh:
        json.dump({"seed": c.SEED, "rows": rows,
                   "details": {"coverage_det_edges": len(det_edges), "coverage_edges_total": e_dedup,
                               "coverage_rand_permille": cov_rand, "entropy_distribution": dist,
                               "entropy_uniform_upper_milli_bits": int(math.log2(len(spec["endings"])) * 1000),
                               "tension_mae_full_milli": mae_all, "tension_curve": curve,
                               "affinity_mae_pairs": cnt, "affinity_mae_abs_sum": num,
                               "consistency_dksr": {"D": len(d), "K": k, "S": s_, "R": r},
                               "density_dry_permille": dens["dry_share_permille"],
                               "density_burst_permille": dens["burst_share_permille"]},
                   "reconciled": [{"label": a, "value": b} for a, b, _ in checks],
                   "proxy": True}, fh, ensure_ascii=False, indent=1)
        fh.write("\n")
    print("wrote out/nm_15_1_metric_catalog.json")
    print("OK nm_15_1_metric_catalog:7 条 proxy 指标已实测并与各章产物逐条对账")
    return 0


if __name__ == "__main__":
    sys.exit(main())

本机实跑 /opt/homebrew/bin/python3 sim/nm_15_1_metric_catalog.py:

spec=雾港夜航  节拍 16(tension 和 52)  对话节点 48  去重边 56  结局 5
全卷代理指标总表(seed=20261016,本机实跑,全部整数,全部 proxy)
   1  分支覆盖率 = 446 千分(阈值 850,首见 §2.2)
   2  结局分布熵 = 1714 毫比特(阈值 1500,首见 §3.1)
   3  张力曲线 MAE = 0 毫(阈值 1000,首见 §5.2)
   4  好感度曲线 MAE = 5739 毫(阈值 12000,首见 §15.1)
   5  一致性残差 = 8 计数(阈值 0,首见 §9.1)
   6  节奏密度偏差 = 5 千分(阈值 0,首见 §7.2)
   7  整数不变量残差 = 0 计数(阈值 0,首见 §1.1)
   分支覆盖率对照:确定性路径 25/56 = 446‰;采样 200 条 56/56 = 1000‰
   结局分布熵:采样 20000 条 {'离港': 10074, '沉没': 5507, '缄默': 3223, '灯守': 1018, '真相': 178}
   好感度曲线 MAE:确定性曲线 vs 随机 2000 条均值曲线,92 个逐步比较,差和 528 点
   一致性残差:D 2 + K 3 + S 1 + R 2 = 8
对账(本节重算值 = 各章产物):
   覆盖率 2.2  本节 446  产物 446  OK
   熵 3.1  本节 1714  产物 1714  OK
   张力 MAE 6.2 路径  本节 0  产物 0  OK
   张力 MAE 6.2 全量  本节 0  产物 0  OK
   一致性残差 9.1  本节 8  产物 8  OK
   密度偏差 7.2  本节 5  产物 5  OK
   好感度曲线 8.1     确定性 4 条曲线逐项一致 True
定义表 lint     条目 7 / 缺字段 0 / 非 proxy 0 / 空清单 0 / 口径漂移 0
wrote out/nm_15_1_metric_catalog.json
OK nm_15_1_metric_catalog:7 条 proxy 指标已实测并与各章产物逐条对账

对账表里每一行都是 assert:覆盖率 2.2 本节 446 产物 446 OK、熵 3.1 1714=1714、张力 MAE 6.2 路径 0=0……任何一条对不上,脚本直接 FAIL。这不是「我复述了一遍各章的数字」,是「我独立算了一遍,和它们撞上了」。

D 层:可 lint 的定义表

定义本身是一份 JSON,落 config/nm_15_1_metric_definition_table.json,每条 12 个字段:

{
  "section": "15.1",
  "tier": "D",
  "spec": "config/story_spec.json",
  "seed": 20261016,
  "note": "全卷 proxy 指标定义总表。每条 kind 恒为 proxy:只做相对比较,不做绝对判断。observed 由 sim/nm_15_1_metric_catalog.py 实跑填入,本表只写定义与口径。",
  "metrics": [
    {"id": 1, "metric": "branch_coverage", "name": "分支覆盖率", "kind": "proxy", "unit": "permille",
     "definition": "走过的去重对话边数 × 1000 // 全部去重边数。去重口径把指向同一目标的并行选项并成一条图边,分母 56;对照的选项口径分母 115。",
     "truth_source": "dialogue[].choices[].goto(去重成 (节点, 目标) 对)", "measures": "一条策略走过的图边占全图的千分比",
     "does_not_measure": ["玩家实际探索到的丰富度", "文本量或演出量", "体验多样性"],
     "allowed_use": ["同一规格内不同策略的相对比较", "采样规模对覆盖的影响", "规格演化前后的回归对照"],
     "first_section": "2.2", "threshold_field": "metrics.coverage_target_permille", "threshold_value": 850},
    {"id": 2, "metric": "ending_entropy", "name": "结局分布熵", "kind": "proxy", "unit": "milli_bits",
     "definition": "采样分布上 5 个结局的 Shannon 熵 × 1000 取整(毫比特):-sum(p log2 p) × 1000。均匀上界 log2(5) = 2321 毫比特。",
     "truth_source": "endings[] 与 dialogue 里的结局节点", "measures": "采样分布离均匀分布有多远",
     "does_not_measure": ["玩家实际体验到的多样性", "单个结局的叙事质量", "稀有结局是否值得存在"],
     "allowed_use": ["同一规格内不同策略 / 采样规模的相对比较", "演化前后分布偏斜的回归对照"],
     "first_section": "3.1", "threshold_field": "metrics.ending_entropy_min_milli_bits", "threshold_value": 1500},
    {"id": 3, "metric": "tension_curve_mae", "name": "张力曲线 MAE", "kind": "proxy", "unit": "milli",
     "definition": "沿路径取经过场景的节拍张力序列,与 metrics.target_tension_curve 同下标逐项相减,sum(|实际 − 目标|) × 1000 // n(毫)。1 点 = 1000 毫。",
     "truth_source": "beats[].tension 与 metrics.target_tension_curve", "measures": "标注张力序列与设计目标曲线的平均绝对偏离",
     "does_not_measure": ["玩家实际感受到的情绪强度", "台词的感染力", "机制层的张力动力学"],
     "allowed_use": ["同一规格内两条曲线的相对偏离", "规格演化前后的回归对照"],
     "first_section": "5.2", "threshold_field": "metrics.tension_mae_max", "threshold_value": 1000},
    {"id": 4, "metric": "affinity_curve_mae", "name": "好感度曲线 MAE", "kind": "proxy", "unit": "milli",
     "definition": "确定性路径(每步取第一个可用选项)的 4 条好感度曲线,与随机策略 N 条采样的逐步均值曲线逐变量逐步相减,sum(|确定性 − 均值|) × 1000 // 比较步数(毫),对齐到较短长度。",
     "truth_source": "characters[].affinity.init 与 dialogue[].choices[].effects.add", "measures": "一条具体路径的关系推进曲线偏离总体基线多远",
     "does_not_measure": ["玩家是否被这段关系打动", "关系设计是否有说服力", "阈值门是否设计得合理"],
     "allowed_use": ["同一规格内两条曲线的相对偏离", "确定性策略与采样基线之间的对照"],
     "first_section": "15.1", "threshold_field": "metrics.affinity_mae_max", "threshold_value": 12000,
     "caveat": "真源有 affinity_mae_max 阈值,却没有对应的 target_affinity_curve 字段——阈值当前没有可比目标,本节按「路径对采样基线」给出实测值,属规格的一处欠声明。"},
    {"id": 5, "metric": "consistency_residual", "name": "一致性残差", "kind": "proxy", "unit": "count",
     "definition": "四类静态失配计数之和:D 声明域失配 + K 秘密失配(见证旗标无门提供者)+ S 立场失配(敌对派系两侧都有 add 提供者)+ R 规则失配(禁区无门可进)。",
     "truth_source": "characters[].affinity / secret、world.factions[].stance、world.rules[] 对 dialogue[].choices[].when / effects 的对齐",
     "measures": "规格里「声明」与「许可」之间的失配条数",
     "does_not_measure": ["叙事失调的主观强度", "玩家会不会察觉", "失配是否该修"],
     "allowed_use": ["同一规格演化前后的残差回归", "四类失配之间的相对占比"],
     "first_section": "9.1", "threshold_field": null, "threshold_value": 4, "threshold_note": "告警阈值 tau = 4,见 9.3;非规格字段"},
    {"id": 6, "metric": "density_deviation", "name": "节奏密度偏差", "kind": "proxy", "unit": "permille",
     "definition": "滑窗(W = 5 节点)密度越出可读带 [250, 750] 千分的窗口占比 = 偏疏窗口占比 + 偏密窗口占比。窗口密度 = 窗口内信息事件数 × 1000 // (4 × 5)。",
     "truth_source": "由路径信息事件算出(新场景 / 新 flag / 新物品 / 有意义选择各算一件),口径见 7.2", "measures": "路径上有多少比例的窗口把信息给得太稀或太密",
     "does_not_measure": ["玩家觉得节奏快还是慢", "文本可读性", "节拍张力的高低"],
     "allowed_use": ["同一规格内不同策略的相对比较", "密度控制参数扰动前后的对照"],
     "first_section": "7.2", "threshold_field": null, "threshold_value": 0, "threshold_note": "可读带 [250, 750] 千分是 7.2 的设计参数;偏差本身只做相对比较"},
    {"id": 7, "metric": "invariant_residual", "name": "整数不变量残差", "kind": "proxy", "unit": "count",
     "definition": "四类整数不变量越界计数之和:好感度越出 [0,100]、tension 越出 [1,5]、flag 取值非布尔、节点数不等于选择数加一。",
     "truth_source": "state.vars / beats[].tension / effects.set / 路径长度", "measures": "整数状态机有没有越界(恒等判据,无容差)",
     "does_not_measure": ["叙事质量", "体验好坏"],
     "allowed_use": ["全书 S 层每节的硬断言", "跨语言(Python / TypeScript / 浏览器)指标一致性"],
     "first_section": "1.1", "threshold_field": null, "threshold_value": 0, "threshold_note": "恒等判据:必须为 0,不设容差"}
  ]
}

S 层脚本最后会 lint 这张表:条目数必须等于 7、每条 kind 必须是 proxy、does_not_measure 与 allowed_use 不能为空、unit / name / first_section 必须与实算行一致(口径漂移为 0)。定义表不是文档,是产物——它和脚本互相钉死,改一个字段就得改另一个。

判读

第一,这张表是「收口」,不是「汇总」。 汇总只是把数字搬到一起;收口是把它们压到同一套字段下,让「怎么算、量什么、能回溯到哪」三件事一次问清。七个首见小节串起来,就是本卷从第 1 章到第 15 章的度量路线图。

第二,量纲是这张表的骨头。 七条指标落在四个量纲上:千分、毫比特、毫、计数。它们不能相加——这正是 15.2 要展开的局限。一张把千分和计数并排的表,如果没有量纲列,就会诱导人去求「总分」。

第三,也是最重要的一点:实测值全落在阈值内,不代表「叙事好」。 覆盖率 446 低于 850、残差 8 高于 0,两个「没达标」的读数并列摆着,指标也没判「好坏」——它只报出偏离,方向留给人判。这一条边界,15.3 会讲透。

自检表

检查项实测合格标准
指标条数7覆盖全卷七条 proxy
重算 vs 产物对账6 / 6 OK逐条 assert 通过
定义表 lint缺字段 0 / 口径漂移 0全通过
好感度曲线对账4 条曲线逐项一致与 8.1 产物一致
全部 proxy7 / 7kind 恒为 proxy

阅读导航:上一节:14.3 演化的告警 · 下一节:15.2 指标的可比性与局限 。

继续阅读

探索更多技术文章

浏览归档,发现更多关于系统设计、工具链和工程实践的内容。

全部文章 返回首页

「narrative」更多文章

  1. 15.3 规模告警
  2. 15.2 求值与遍历的开销
  3. 15.1 规格规模的增长