report の設計

設計目標

ベンチマークのレポートは、監査記録から再現でき、安全に共有できなければなりません。report は、JSONL イベントストリームから Plot IR(ir_model)への、そして Plot IR から JSON、SVG、HTML への純粋な射影です。何が速いかを判断することはなく、ストリームの内容を示すだけです。また、無効な計測を有効なもののように見せることは決してありません。

数学的背景

射影

ストリームをイベントの系列とします。valid が真で batch_sink が "kept" である観測を OO、ステータスが invalid または infrastructure_failure である検証のキー (case,implementation,dataset)(\text{case}, \text{implementation}, \text{dataset}) の集合を FF と書きます。プロットされる点は次のとおりです

P={ (dataseto,elapsedo,implementationo)  :  o∈O, (caseo,implementationo,dataseto)∉F },P = \{\, (\text{dataset}_o, \text{elapsed}_o, \text{implementation}_o) \;:\; o \in O,\ (\text{case}_o, \text{implementation}_o, \text{dataset}_o) \notin F \,\},

これらはストリームの順序で並びます。射影は点に反する証拠について単調です。失敗する検証を追加しても点が取り除かれるだけで、無効な観測を追加しても点は増えません。

座標

プロットは 960×420960 \times 420 の view box のうち矩形 [76,880]×[102,354][76, 880] \times [102, 354] を占めます。最初に現れた順に mm 個の異なる x カテゴリがあるとき、カテゴリ ii は次の位置に置かれます

X(i)=76+i 804m−1(m>1),X(0)=478(m=1).X(i) = 76 + i\,\frac{804}{m - 1} \quad (m > 1), \qquad X(0) = 478 \quad (m = 1).

vmin⁡v_{\min} と vmax⁡v_{\max} を y 値の最小値と最大値とします。y の範囲には余白が加えられます。

[ℓ,h]={[vmin⁡−0.08 w, vmax⁡+0.08 w],w=vmax⁡−vmin⁡>0,[v−π, v+π],π=0.1max⁡(∣v∣,1),vmin⁡=vmax⁡=v,[\ell, h] = \begin{cases} [v_{\min} - 0.08\,w,\ v_{\max} + 0.08\,w], & w = v_{\max} - v_{\min} > 0, \\[2pt] [v - \pi,\ v + \pi],\quad \pi = 0.1\max(\lvert v\rvert, 1), & v_{\min} = v_{\max} = v, \end{cases}

空のプロットでは [0,1][0, 1] です。どの場合も h−ℓ>0h - \ell > 0 なので、線形写像

Y(v)=354−(v−ℓ) 252h−ℓY(v) = 354 - (v - \ell)\,\frac{252}{h - \ell}

は well-defined であり、プロットされるすべての値について ℓ<v<h\ell < v < h が成り立つため、すべての点がプロット領域の厳密に内側に置かれます。ヒートマップのセルは不透明度 0.18+0.72 (v−ℓ)/(h−ℓ)0.18 + 0.72\,(v - \ell)/(h - \ell) を使うため、これは 0.180.18 と 0.900.90 の間に厳密に収まります。見えないセルも、完全に飽和したセルもありません。

グリッド線は j=0,…,4j = 0, \dots, 4 について Y=102+63jY = 102 + 63j に描かれ、目盛り値は h−(h−ℓ) j/4h - (h - \ell)\,j/4 を小数点以下 3 桁に丸めたものです。mm 個のカテゴリがある場合、ラベルは ⌈m/10⌉\lceil m/10\rceil カテゴリごとと最後のカテゴリに描かれるため、表示されるラベルは最大 11 個です。

設計上の決定

副作用を外に置いた純粋な射影

問題。 レポートはレンダラの変更後に再生成され、レビューで比較されます。選択。 document_from_jsonl、plot_json、plot_svg、html は値を受け取り文字列を返します。ファイル IO、標準ストリーム、ブラウザを開く処理は cli にあります。理由。 同じ JSONL からはどのターゲットでも同じバイト列が得られ、テストにファイルシステムは不要で、HTML をより大きなアプリケーションの中で生成できます。

失敗は系列を取り除き、見えるまま残る

問題。 誤った結果を返す高速な実装は、勝者のように見えてしまいます。選択。 失敗した検証は、そのケースとデータセットにおけるその実装の点を取り除き、不一致の行を追加します。最小化された失敗は、リプレイコマンド付きの反例の行を追加します。理由。 差分セクションはプロットの上にあるため、読み手はなぜ系列が欠けているのかがわかります。

平均線付きの生の点

問題。 要約は分布を隠し、生の点群は傾向を隠します。選択。 すべての観測をツールチップ付きで描き、線を使う種類ではカテゴリごとの平均でカテゴリを結びます。理由。 描かれた点の平均は、目がすでに見積もっている重心です。頑健な統計量と判断は stats の役割であり、追加のプロットとして加えられます。線は目安であって、レポートが保証する推定値ではありません。

カテゴリカルな x 軸

問題。 スケールは整数、形状、レイアウト、名前のいずれでもありえます。選択。 PlotPoint.x は文字列で、軸は最初に現れた順にカテゴリを等間隔に配置します。理由。 数値軸にするとスケールごとに型が必要になります。その代償として、間隔は大きさを反映せず、パレートのビューは 2 次元のフロントではなくカテゴリカルな散布図になります。

エスケープの順序

テキストは &、<、>、"、' をこの順に置換してエスケープされます。& は最初でなければなりません。< の後に置換すると、生成された &lt; が &amp;lt; になってしまいます。後続の置換が持ち込む & はすべてすでにエンティティの一部なので、結果を一度デコードするとちょうど入力に戻ります。同じ関数が要素のテキストと属性値をエスケープします。

自己完結型の出力

HTML は CSS とインライン SVG を埋め込み、フォント、スクリプト、画像を読み込まず、color-scheme: light を宣言します。issue に添付したり JSONL と一緒にアーカイブしたりしても、10 年後も同じように描画されます。

バージョンによる関門

artifact_version が mmka_1 以外の文字列である行は、その行番号とともに拒否されます。このフィールドを持たない行は受け入れられるため、手書きのフィクスチャや以前のストリームも読めます。文字列でないバージョンはエラーです。JSON 出力は schema_version mmks_1 を持ちます。

正しさと不変条件

  • 決定性。 すべての関数は純粋で、等しい入力からは等しい文字列が得られます。
  • 除外。 無効な観測、破棄された観測、失敗した検証の対象となる観測からは、どの点も生じません(PP の定義)。
  • 包含。 すべての点はプロット領域の厳密に内側にあり、ヒートマップの不透明度はすべて (0.18,0.90)(0.18, 0.90) に収まります(上で導いたとおり)。
  • エスケープ。 イベント、タイトル、単位、系列名に由来するすべてのテキストは、SVG や HTML に達する前にエスケープ関数を通ります。
  • 計算量。 解析はストリームのサイズに対して線形ですが、各点を失敗キーのリストと照合するため O(∣O∣⋅∣F∣)O(\lvert O\rvert \cdot \lvert F\rvert) かかります。NN 個の点、mm 個のカテゴリ、SS 個の系列を持つプロットの描画は、線の平均がセルごとに再計算されるため O(N(m+S)+mSN)O(N(m + S) + mSN) です。

採用しなかった代替案

  • JavaScript のグラフライブラリ。 スクリプトや CDN が必要になり、出力がブラウザのランタイムに依存することになります。
  • 要約だけを描画する。 二峰性や外れ値が隠れます。
  • 数値の x 軸。 ケースごとにスケールの型が必要です。先送りしました。
  • 失敗した実装を時間ゼロまたは無限大として扱う。 どちらも計時の軸上では誤解を招く値です。

境界

  • JSONL からの射影は 1 つの Scaling プロットを構築します。他の種類のプロットは、呼び出し側が Plot IR で構築すれば描画されますが、イベントからそれらを導出するものはまだありません。
  • 探索フェーズと確認フェーズの観測は一緒にプロットされ、x の値はスケールではなくデータセットのインデックスです。
  • ターゲットは呼び出し側から渡され、ストリームからは読まれません。
  • ここでは統計量、判断、環境の比較は計算されません。
  • スタイル、色、レイアウトは互換性の約束の対象ではありません。約束されるのは mmks_1 JSON の構造です。