安全かつ堅牢なMFA構成

MFAは安全性のために堅牢性を犠牲にして推進されているため両方を考慮して認証方法を選定しなければならない。 リカバリーコードによる復旧可能性は期待しないものとする。 脅迫耐性は即時使用可能な認証方法はすべて低いため考慮しない。

比較

認証方法 役割 種別 媒体 喪失機会 喪失耐性 侵害機会 侵害耐性 検証性 機密性 堅牢性 安全性
リカバリーコード 所持 PC/Vault Common Low Rare Middle Yes High Low Middle
パスワード(共通) 知識 Browser Rare High Common Low No High High Low
パスワード(個別) 知識 Browser Common Low Common High No High Low High
パスワード(パターン) 知識 Browser Rare Middle-High Common Low-Middle No High Middle-High Low-Middle
物理キー(非同期) 所持 Key Common Low Rare High Yes High Low High
物理キー(同期) 所持 Key Common High Rare High Yes Low High High
FIDO(非同期) 所持 All Common Low Rare High Yes High Low High
FIDO(同期) 所持 All Common High Rare High Yes Low High High
認証アプリ(非同期) 補助 知識/所持 Mobile Common Low Rare High Yes High Low High
認証アプリ(同期) 補助 知識/所持 Mobile Common High Rare High Yes Low High High
Email 補助 知識 Browser/Mobile Rare High Common Low-Middle Yes Low High Low-Middle
SMS 補助 知識/所持 Mobile Common High Common Low Yes Low High Low
  • FIDOは主認証方式の安全性を単独使用可能な水準に強化する
  • 認証アプリは唯一安全な補助認証方式
  • MFAは不都合な事実を隠して推進されている
    • 安全性の高い認証方式ほど紛失や盗難などにより認証を喪失しやすい(堅牢性が低い)
    • リカバリーコードは物理的復旧手段の脆弱な代替手段にすぎない
    • 電子的復旧手段の確保は相対的に脆弱な二段階認証またはリカバリーコードへの間接的ダウングレードを避けられない
  • 標的型攻撃を考慮しない場合、パスワード+EmailまたはSMSの二段階認証で足りる
    • 高強度認証方式を導入しても物理的復旧手段なしで堅牢性(喪失耐性)を上げるには物理デバイスに依存しない低強度認証方式に間接的にダウングレードしなければならない
    • 使用頻度と認証頻度が少なければランダムなパスワードを設定して常にパスワードリセットで認証するのが最も安全
      • あらゆるサービスは認証頻度が最小となるよう設計されなければならない
      • 物理キーは登録数に上限があるためすべての認証に使うには適さない
    • 物理キーは家庭内でまで使うには煩雑で普遍化するとは考えにくい
    • 認証アプリとEmailとSMSは本質的に同種の認証方式
    • 認証アプリは安全だがEmailとSMSは同種の大きな脆弱性があるため実質的な差はない
    • 非標的型攻撃では長寿命の認証情報と短寿命の認証情報のいずれかの漏洩を防げば足り、攻撃前に失効する短寿命の認証情報の厳格な安全確保は不要
      • 漏洩した大量の長寿命認証情報を控え短寿命認証情報を収集および即時侵害する攻撃のリスクが一般化すれば必要
      • 長寿命認証情報の2-3年ごとの変更が必要
      • 何らかの懸念または決済情報等の高リスクがある場合はパスワード+認証アプリ以上の認証強度にするのが望ましい
    • 自分に標的となる価値または機会があり標的となる状況にあるかの確認は常に必要
  • 標的型攻撃を考慮する場合、物理キーまたは認証アプリが必要となる
    • 標的型攻撃では短寿命の認証情報も厳格な安全確保が必要
    • 盗難対策に依然としてパスワードが効果的
  • よって非厳格なサービスでも標的用の厳格な認証方法と非標的用の非厳格な認証方法の両方を提供しなければならない
  • ゼロデイ攻撃は侵害機会を減らすことでリスクを軽減可能
  • 認証の使用方法や使用環境も安全化しなければ認証方式の効果は限定的
    • 認証を使用するブラウザやデバイスを厳格に運用しなければどれほど安全な認証を行っても認証後に認証(セッション)やデバイスをハイジャックされるリスクが高い
    • 使用方法か使用環境が危険な人間に認証アプリや物理キーを強制しても無駄
    • 認証方式の安全性だけ高めてもリスク軽減への寄与は小さい
    • 個人的には生活用(高価値情報用。決済、ライフライン、公的サービス、重要連絡、仕事等)と遊び用(高リスク行動用。ブラウジング、交友、SNS、アプリ、ゲーム等)のデバイスを分ける
      • 認証アプリや物理キーの使用より侵害対象(ブラウザ、PC、モバイルデバイスなど)の分離のほうが効果が大きく先決(侵害範囲の局所化)
    • 組織的には専用デバイスを貸与する
  • 物理キー(同期)、FIDO(同期)、認証アプリ(同期)、Email、SMSは使用状況から活動を分析可能であり機密性が低い

強度

  1. パスワード(またはマジックリンク)
  2. パスワード+Email(またはSMS)
  3. パスワード+認証アプリ
  4. FIDO(物理キーまたは生体認証)
  5. FIDO+パスワード
  6. FIDO+認証アプリ
  7. FIDO+認証アプリ+パスワード

リカバリーコード

  • 物理的および電子的な喪失および侵害に脆弱 (喪失、侵害)

運用上の大きな脆弱性を作ることになり危険。 物理的復旧手段の脆弱な代替手段にすぎない。

パスワード

  • 物理的および電子的な喪失および侵害に比較的堅牢
  • 詐取のリスクが高い (侵害)
  • 不適切運用のリスクが高い (侵害)
  • 運用の健全性および実際の安全性が検証困難
  • 盗難対策に効果的

短期的には個人的に優れた方法として運用可能だが長期的には詐取または漏洩による侵害リスクが高く多要素認証ないし多段階認証(基本的にEmailかSMSで十分)が必要。 組織的に優れた方法として運用不可能(記憶できないパスワードはパスワードではなく記憶できる範囲で適切なパスワードであるかは検証できず非電子的漏洩の認識と侵害前の対処が困難)。 認証方法が実質的に一要素(デバイス認証やEmail認証を行うノートPCと物理キーは一緒に盗まれる)である場合多要素の一つとして盗難対策に効果的(生体認証や別デバイスでのSMS認証に高度化可能)。

物理キー (セキュリティキー)

  • 物理的復旧手段がなければデッドロックのリスクを負うか脆弱な電子的復旧手段へのダウングレードが必要 (喪失、侵害)
  • 盗難に脆弱 (侵害)
  • 小型デバイスへの適用が困難

物理的復旧手段がなくダウングレードを許容しないなら認証喪失のリスクが高く危険。 物理的復旧手段がなくデッドロックのリスクを許容しないなら最終的にパスワードまたはリカバリーコードによる原始的な認証にダウングレードすることになる(実践的にはどの段階でデッドロックのリスクを許容するか、またはパスワードかリカバリーコードを使用するかの選択となる)。 物理的復旧手段(自社セキュリティ部門または社内ネットワークからの復旧)があるなら非常に優れている。

FIDO

  • 主認証方式に認証媒体の所持要素を追加し強化する
  • 認証経路(手順)も安全化される
  • 物理キーと共通の運用脆弱性
  • 認証が喪失可能になり堅牢性が下がる (喪失)
  • 電子的復旧手段へのダウングレードが必要 (侵害)
  • 認証情報を外部に保存 (中間者)
  • 機密性を第三者に依存 (中間者)
  • FIDO認証後にパスワード認証を追加することでFIDO+パスワードなどの構成が可能
    • 追加パスワード認証にヒントなどのユーザー設定値の開示による正規サービス証明によるフィッシング対策が必要
      • ユーザー設定値の暗号化が必要

ユーザーの知識(パスワード)または所持(生体認証、物理キー)にクライアントの所持(デバイス認証)を足すことで安全性を高める認証方式。 認証先へのパスワード入力機会を減らすことによるフィッシング対策効果が大きい。 しかし盗難対策としてパスワード認証用と異なるパスワード(パスフレーズ)の入力を求める効果は高い。 基本的に電子的復旧手段を用意するのが前提であり電子的復旧手段であるパスワード等の低強度認証方式への攻撃リスクは残る。 認証情報が認証媒体と一体化しており同期しない限り移動不可能であるため認証媒体の変更コストが非常に高い問題を調整不可能であることが使いにくさの根底にある(同期すれば同期サービスに依存し機密性が下がる。デバイス識別子の代わりにマスターパスワードを設定でき個体差のない共通規格の生体認証器があれば同期を要さず認証媒体を容易に変更可能になる。マスターパスワードはTPMに保存すれば解読不能のはず)。

認証アプリ

Authenticatorなどのトークンジェネレーター。

  • 安全化された補助認証方式
  • 本質的にEmailやSMSと同種の認証方式
  • 物理キーと共通の運用脆弱性
  • Emailより認証媒体が安全
  • SMSより認証媒体と認証経路が安全
  • 認証情報を外部に保存 (中間者)
  • 機密性を第三者に依存 (中間者)

認証媒体と認証経路の安全性を高めたEmailまたはSMSであるためこれらの厳格な安全確保が不要な非標的型攻撃に対しては不要。 EmailおよびSMSの代わりとなる安全化された補助認証方式であるためパスワード等の主認証方式の代わりではなくFIDOと直交し併用が効果的。

Email

厳格に運用できれば優れている。

SMS

受信のみかつ不審なアプリを入れておらずかつSIMスワップのリスクが低くかつ標的にされなければ優れている。

ハフマン符号の非効率性の理論的証明とハフマン符号を超える非肥大化保証ASCII文字圧縮エンコーディング

他の圧縮エンコーディングが圧縮率が低かったり肥大化リスクがあったり辞書の共有が厄介だったりしたので非辞書式非肥大化保証ASCII文字圧縮エンコーディング(辞書の意味が多義的で扱いづらいがとりあえず辞書式のデメリットがないという意味で非辞書式と書いておく)を作ってみた。デフォルトで使ってた圧縮エンコーディングが一部の用途(KVS、RPC、IoT通信など)でデータサイズを意図せず数十%増加させてたという事態を避けるのが主な開発目的である。昨年のような革新的新アルゴリズムではないがデータベース、RPC、ログなどの値として一般的な単語、数値、識別子において現時点でASCIIコードの最高のハフマン符号実装と思われるHPACKを超える圧縮率の圧縮方式である。なおgzipなど通常の圧縮アルゴリズムは計算量と負荷が大きいため用途が異なりgzipは暗号通信が解読可能になる脆弱性もある。まずソースコードのメモをコピペ。

ASCIIコード用デルタエンコーディングアルゴリズム。
非辞書式圧縮文字エンコーディング。
定数計算量の操作のみで構成。
圧縮展開いずれも時間空間ともに線形計算量。
圧縮前よりデータサイズが増加しないことを保証。
ASCIIと完全に相互変換可能なため透過的に使用できる。

圧縮文字エンコーディングは転送または保存のために組み込み系などで使用される。
通常の圧縮アルゴリズムでは負荷が高く使用不能または肥大化する数百バイト以下の
文字列のデータサイズを平均20-30%、最大50%削減可能。
キャッシュやインメモリKVSの容量を5-10%以上拡大しRPCやIoTのトラフィックを
5-10%以上削減できる可能性がある(個別に専用のエンコーディングを適用すべき場合も多い)。
(NB-)IoTのパケットサイズは数十から数百バイト、最大512バイトのペイロード制限
がある場合もあり圧縮エンコーディングはこのレンジの文字列の圧縮に適合する。
SQL ServerではSCSUが使われている。
Protobufではsintが使われている。

他の圧縮エンコーディングとの比較

Delta ASCII:
ASCII互換。
最大50%圧縮。
非肥大化保証。
出現頻度の高い2文字を1byteに圧縮できるときのみ圧縮する。
文字ごとが望ましいが面倒なので簡易化。

ZSCII:
ASCII下位互換。
最大33%圧縮(1/3)?
ASCIIのサブセット(制御文字に制限)。
よくわからないが実装を見ると肥大化しそう。
セグメントIDとオフセットの組または連続のようだがこの方式はあまり
圧縮率が高くなかった。

Packed ASCII:
ASCII下位互換。
最大25%圧縮(1/4)。
ASCIIのサブセット(大文字+数字+記号)。

SCSU:
ASCII上位互換。
ASCII文字はUTF-8からは圧縮されない。

HPACK:
ASCII互換。
最大37.5%圧縮。
ハフマン符号の最も優れたASCIIコード用実装と思われるが16進数を超える
ランダム文字列以外DAより圧縮率が低い。

ANS/FSE:
理論上最適に近くともハフマン符号同様頻度分布が正しいことが前提なので同じく
単語やBase64など事前知識により部分ごとに最適な符号表を使用するほど効率的ではないと思われる。
そしてANS/FSEはそれに適したアルゴリズムではないように見える。
エンコーディングとしては状態の初期化コストも無視できないものとなる懸念がある。
また1文字など非常に短い文字列では大きく肥大化する懸念がある。
https://arxiv.org/abs/1311.2540
https://github.com/Cyan4973/FiniteStateEntropy
https://www.reddit.com/r/programming/comments/7uoqic/finite_state_entropy_made_easy/?rdt=38141

lz-string:
圧縮アルゴリズム。
ASCII上位互換。
圧縮率が非常に高いように見えるがUTF-16(全文字2バイト以上)としての圧縮率
であるためASCIIやバイナリとしては肥大化しており非効率。
数百文字以上では肥大化する以上に圧縮されるが入力に準じたサイズの辞書を
生成するため入力サイズが大きければ考慮が必要。
数文字程度の短い文字列の圧縮展開でも低速なため集中的な使用には適さない。

次に圧縮率の比較を行う。ワードは英単語使用頻度トップ5000をランダムに選択しハイフンで、テキストはZipf 1.0で選択し空白で接続している。サンプルは次の代表的なダミーテキストである。

On the other hand, we denounce with righteous indignation and dislike men who are so beguiled and demoralized by the charms of pleasure of the moment, so blinded by desire, that they cannot foresee the pain and trouble that are bound to ensue; and equal blame belongs to those who fail in their duty through weakness of will, which is the same as saying through shrinking from toil and pain. These cases are perfectly simple and easy to distinguish. In a free hour, when our power of choice is untrammelled and when nothing prevents our being able to do what we like best, every pleasure is to be welcomed and every pain avoided. But in certain circumstances and owing to the claims of duty or the obligations of business it will frequently occur that pleasures have to be repudiated and annoyances accepted. The wise man therefore always holds in these matters to this principle of selection: he rejects pleasures to secure other greater pleasures, or else he endures pains to avoid worse pains.

jsongoogle.comのhttpヘッダにある次のもの。基本的にURLのような断片化したテキストが少ないとDA、多いとHPACKの方が圧縮率が高くなるがHPACKは括弧により大きく肥大化するため基本的にjsonと相性が悪い。

{"group":"gws","max_age":2592000,"endpoints":[{"url":"https://csp.withgoogle.com/csp/report-to/gws/other"}]}

DA(Delta ASCII)は文字テーブルをセグメント化しセグメント内の出現頻度の高い組み合わせを圧縮しているが平均的にはより圧縮率の高い素朴なデルタエンコーディングもあるためこのシミュレーション結果と比較する。Hはヘッダー、Eはエスケープ、Sはシフトで続く数字はそのためのビット数である。HPACKはHPACKの辞書によるハフマン符号化である(このためヘッダとしての構造的圧縮とは異なる)。左の数値は減少したサイズの比率(1 - after / before)で右は圧縮アルゴリズムにおける圧縮率(before / after)である。ここではわかりやすく左を圧縮率とする。圧縮率がマイナスのものは肥大化している。

'Delta   comp. ratio random number', 0.422590625, 1.7318735082886383
'HPACK   comp. ratio random number', 0.27509062500000003, 1.3794827801751082
'SimH2E5 comp. ratio random number', 0.46875, 1.8823529411764706
'SimH3E5 comp. ratio random number', 0.46875, 1.8823529411764706
'SimH2S5 comp. ratio random number', 0.46875, 1.8823529411764706
'SimH3S5 comp. ratio random number', 0.46875, 1.8823529411764706
'SimH2S0 comp. ratio random number', 0.46875, 1.8823529411764706

'Delta   comp. ratio random hex', 0.304153125, 1.4370977810312076
'HPACK   comp. ratio random hex', 0.25192812499999995, 1.3367699460696876
'SimH2E5 comp. ratio random hex', 0.019862500000000005, 1.0202650138373444
'SimH3E5 comp. ratio random hex', -0.040043749999999934, 0.961498013905665
'SimH2S5 comp. ratio random hex', 0.14002812499999995, 1.1628287262301455
'SimH3S5 comp. ratio random hex', 0.14002812499999995, 1.1628287262301455
'SimH2S0 comp. ratio random hex', 0.18818437499999996, 1.2318067911048152

'Delta   comp. ratio random 36', 0.06517968750000003, 1.0697242952773345
'HPACK   comp. ratio random 36', 0.25349999999999995, 1.3395847287340925
'SimH2E5 comp. ratio random 36', 0.05402343750000005, 1.0571086426890202
'SimH3E5 comp. ratio random 36', 0.0036562500000000275, 1.0036696672207759
'SimH2S5 comp. ratio random 36', 0.15463281250000005, 1.1829179258273494
'SimH3S5 comp. ratio random 36', 0.15463281250000005, 1.1829179258273494
'SimH2S0 comp. ratio random 36', 0.1783828125, 1.2171118316582197

'Delta   comp. ratio random 64', 0.17917968750000002, 1.2182934373958978
'HPACK   comp. ratio random 64', 0.188125, 1.2317167051578137
'SimH2E5 comp. ratio random 64', -0.17171874999999992, 0.8534471262835045
'SimH3E5 comp. ratio random 64', -0.25217187499999993, 0.7986124109359987
'SimH2S5 comp. ratio random 64', -0.010890625000000043, 0.9892267029383125
'SimH3S5 comp. ratio random 64', -0.010890625000000043, 0.9892267029383125
'SimH2S0 comp. ratio random 64', 0.09820312499999995, 1.1088971671142684

'Delta   comp. ratio word 3-6', 0.2918974981659963, 1.412224921406116
'HPACK   comp. ratio word 3-6', 0.21294680124459286, 1.2705621444412303
'SimH2E5 comp. ratio word 3-6', 0.2741392830942805, 1.3776747752143306
'SimH3E5 comp. ratio word 3-6', 0.2741139864916142, 1.377626764244642
'SimH2S5 comp. ratio word 3-6', 0.2740128000809491, 1.3774347538241751
'SimH3S5 comp. ratio word 3-6', 0.2740128000809491, 1.3774347538241751
'SimH2S0 comp. ratio word 3-6', 0.14601199058966385, 1.1709766284546343

'Delta   comp. ratio word 5-10', 0.3177409624576546, 1.4657189498027479
'HPACK   comp. ratio word 5-10', 0.2369947561371757, 1.3106069821189636
'SimH2E5 comp. ratio word 5-10', 0.28957260197688983, 1.4076033705663336
'SimH3E5 comp. ratio word 5-10', 0.28955713335498945, 1.4075727225222088
'SimH2S5 comp. ratio word 5-10', 0.2894333843797856, 1.4073275862068966
'SimH3S5 comp. ratio word 5-10', 0.2894333843797856, 1.4073275862068966
'SimH2S0 comp. ratio word 5-10', 0.22670812257335993, 1.2931727710987977

'Delta   comp. ratio word 1', 0.32395864291188936, 1.479199444701527
'HPACK   comp. ratio word 1', 0.2422142622514899, 1.3196342319283325
'SimH2E5 comp. ratio word 1', 0.3017002706042452, 1.4320498174405842
'SimH3E5 comp. ratio word 1', 0.3017002706042452, 1.4320498174405842
'SimH2S5 comp. ratio word 1', 0.3012935821432482, 1.4312162797465804
'SimH3S5 comp. ratio word 1', 0.3012935821432482, 1.4312162797465804
'SimH2S0 comp. ratio word 1', 0.2352223490951182, 1.3075695907389606

'Delta   comp. ratio word 2', 0.2984751349197725, 1.4254662233328514
'HPACK   comp. ratio word 2', 0.2732514759679815, 1.375991786611379
'SimH2E5 comp. ratio word 2', 0.3424173276830019, 1.5207213360359566
'SimH3E5 comp. ratio word 2', 0.34238835162447023, 1.5206543291473893
'SimH2S5 comp. ratio word 2', 0.2520337571081893, 1.3369587324339245
'SimH3S5 comp. ratio word 2', 0.2520337571081893, 1.3369587324339245
'SimH2S0 comp. ratio word 2', 0.3073345648158209, 1.4436984281366674

'Delta   comp. ratio word 4', 0.3330567982133731, 1.4993780539649715
'HPACK   comp. ratio word 4', 0.28805858344009694, 1.4046099534874574
'SimH2E5 comp. ratio word 4', 0.35931713327592607, 1.560834621835884
'SimH3E5 comp. ratio word 4', 0.3592751279412485, 1.5607322949503117
'SimH2S5 comp. ratio word 4', 0.22777392728876567, 1.2949575718015667
'SimH3S5 comp. ratio word 4', 0.22777392728876567, 1.2949575718015667
'SimH2S0 comp. ratio word 4', 0.3419794313877863, 1.519709333872392

'Delta   comp. ratio word 6', 0.3441845670148005, 1.524819255088448
'HPACK   comp. ratio word 6', 0.2926721326212379, 1.4137715281964383
'SimH2E5 comp. ratio word 6', 0.3644755979780424, 1.5735037031126458
'SimH3E5 comp. ratio word 6', 0.3644087525960211, 1.5733382171079593
'SimH2S5 comp. ratio word 6', 0.22031315908970417, 1.282566214446412
'SimH3S5 comp. ratio word 6', 0.22031315908970417, 1.282566214446412
'SimH2S0 comp. ratio word 6', 0.353072697810468, 1.5457687387987644

'Delta   comp. ratio word 8', 0.34956916567772556, 1.5374424877042678
'HPACK   comp. ratio word 8', 0.2947749514128958, 1.417987069522655
'SimH2E5 comp. ratio word 8', 0.3670570833978295, 1.579921306913905
'SimH3E5 comp. ratio word 8', 0.3670072063705003, 1.5797968161155957
'SimH2S5 comp. ratio word 8', 0.21643878024869723, 1.2762244669502574
'SimH3S5 comp. ratio word 8', 0.21643878024869723, 1.2762244669502574
'SimH2S0 comp. ratio word 8', 0.3583647214626008, 1.558517795778763

'Delta   comp. ratio word 1 upper', 0.2063318265004458, 1.2599724083563264
'HPACK   comp. ratio word 1 upper', 0.0559196633870892, 1.0592318907813638
'SimH2E5 comp. ratio word 1 upper', 0.17357776352630183, 1.2100352046030964
'SimH3E5 comp. ratio word 1 upper', 0.1453285573508939, 1.170040263543192
'SimH2S5 comp. ratio word 1 upper', 0.20617540786160082, 1.2597241379310344
'SimH3S5 comp. ratio word 1 upper', 0.20617540786160082, 1.2597241379310344
'SimH2S0 comp. ratio word 1 upper', 0.17534529414525035, 1.2126287437643444

'Delta   comp. ratio word 1 camel', 0.2663183744975052, 1.3629890203603028
'HPACK   comp. ratio word 1 camel', 0.21825092678043512, 1.279182840449798
'SimH2E5 comp. ratio word 1 camel', 0.026825796561918303, 1.0275652565256526
'SimH3E5 comp. ratio word 1 camel', -0.010949304719150232, 0.9891692840896783
'SimH2S5 comp. ratio word 1 camel', 0.1149989832788475, 1.129942204704926
'SimH3S5 comp. ratio word 1 camel', 0.1149989832788475, 1.129942204704926
'SimH2S0 comp. ratio word 1 camel', 0.12571366003973028, 1.143790031130354

'Delta   comp. ratio text 100', 0.35245982450951396, 1.544305724725944
'HPACK   comp. ratio text 100', 0.2929113674455289, 1.414249860568879
'SimH2E5 comp. ratio text 100', 0.3682342502218279, 1.5828651685393258
'SimH3E5 comp. ratio text 100', 0.36793847973972194, 1.582124473561067
'SimH2S5 comp. ratio text 100', 0.3692201518288475, 1.5853391684901532
'SimH3S5 comp. ratio text 100', 0.3692201518288475, 1.5853391684901532
'SimH2S0 comp. ratio text 100', 0.3615301192940944, 1.5662445954292774

'Delta   comp. ratio text 500', 0.35289073250503555, 1.5453340729783038
'HPACK   comp. ratio text 500', 0.2964122609337295, 1.4212868480725624
'SimH2E5 comp. ratio text 500', 0.3719960911792274, 1.5923467767545252
'SimH3E5 comp. ratio text 500', 0.37159723191671823, 1.591336083782926
'SimH2S5 comp. ratio text 500', 0.3724148934048621, 1.5934093870157933
'SimH3S5 comp. ratio text 500', 0.3724148934048621, 1.5934093870157933
'SimH2S0 comp. ratio text 500', 0.3686855593004008, 1.5839967146828406

'Delta   comp. ratio text 1000', 0.35317733768762916, 1.5460188058733615
'HPACK   comp. ratio text 1000', 0.29711078487181797, 1.422699308051889
'SimH2E5 comp. ratio text 1000', 0.3723522185936423, 1.5932502744761086
'SimH3E5 comp. ratio text 1000', 0.37209255874804004, 1.5925914144386302
'SimH2S5 comp. ratio text 1000', 0.37293145978767817, 1.5947220054468139
'SimH3S5 comp. ratio text 1000', 0.37293145978767817, 1.5947220054468139
'SimH2S0 comp. ratio text 1000', 0.3689866275179515, 1.5847524689794885

'Delta   comp. ratio country', 0.30586832061068703, 1.4406488418448002
'HPACK   comp. ratio country', 0.23847805343511452, 1.3131597907464838
'SimH2E5 comp. ratio country', 0.05405534351145036, 1.0571442981792505
'SimH3E5 comp. ratio country', -0.002934160305343436, 0.9970744238042004
'SimH2S5 comp. ratio country', 0.13188215648854962, 1.151917343335669
'SimH3S5 comp. ratio country', 0.13188215648854962, 1.151917343335669
'SimH2S0 comp. ratio country', 0.130462786259542, 1.1500370360209597

'Delta   comp. ratio sample', 0.3544176706827309, 1.5489891135303266
'HPACK   comp. ratio sample', 0.29518072289156627, 1.4188034188034189
'SimH2E5 comp. ratio sample', 0.3644578313253012, 1.5734597156398105
'SimH3E5 comp. ratio sample', 0.3624497991967871, 1.568503937007874
'SimH2S5 comp. ratio sample', 0.3654618473895582, 1.5759493670886076
'SimH3S5 comp. ratio sample', 0.3654618473895582, 1.5759493670886076
'SimH2S0 comp. ratio sample', 0.35843373493975905, 1.5586854460093897

'Delta   comp. ratio json', 0.17592592592592593, 1.2134831460674158
'HPACK   comp. ratio json', 0.16666666666666663, 1.2
'SimH2E5 comp. ratio json', 0.15740740740740744, 1.1868131868131868
'SimH3E5 comp. ratio json', 0.12962962962962965, 1.148936170212766
'SimH2S5 comp. ratio json', 0.2129629629629629, 1.2705882352941176
'SimH3S5 comp. ratio json', 0.2129629629629629, 1.2705882352941176
'SimH2S0 comp. ratio json', 0.18518518518518523, 1.2272727272727273

見ての通りDAは特に数値と1語においてハフマン符号のHPACKより圧縮率が高くHEXの圧縮率も高い。これは主に通常の圧縮エンコーディングでは圧縮してもバイト単位で溢れたビットが1バイトに切り上げられてしまうのに対してDAが常にビットを溢れさせず圧縮するからである(文字列が長くなると素の圧縮率の高さが主となり上記の数値となる)。HPACKと違い大文字でも圧縮率が高いので大文字コマンドの圧縮にも優れている。その他でも16進数を超えるランダム文字列(以下ランダム文字列。識別子は一般的にHEXなので問題ない。トークンやセッションIDは一般的に64進数なので問題あるがKVS、RPC、IoT通信においてこれを含む用途の比率は小さいと思われる。32進数はマイナーだし未対応)以外すべてにおいてHPACKを超える圧縮率となっており値として使用される単純なASCII文字列の圧縮エンコーディングとして一般的に優れている(httpヘッダのように断片的で複雑な文字列が多いデータには向かない)。一方HPACKは一部の記号を多用すると2倍以上、制御文字では3倍以上に肥大化する可能性があり断片化によるものも含めランダム性のある文字列の比率が高い場合にDAより高圧縮率となる。HPACKはhttpヘッダ頻出文字に最適化したせいか疑似テキストでもサンプルテキストでも最も圧縮率が低いがDAも非常に最適化が不足している状態であるため偏りをなくしたとしてもハフマン符号よりDAの方が一般的に圧縮率が高くなる可能性が高い(大文字小文字数字の各文字列すべてでDAより圧縮率が高くなるよう短いハフマン符号を割り当てることは困難であり後述するように方式としては理論的に不可能である。また英数字62文字のみの符号化に必要な最小平均ビット数はぎりぎり6ビットでありこれらを踏まえるとHPACKの英数字のハフマン符号はすでに最適に近いと思われる。HPACKの最小ビット数である5ビット符号をすべて小文字に集めて頻度順に割り当て小文字のみおよび小文字主体で比較してもDAとの圧縮率の差は1/3-1/4程度しか縮まらないことからさらに最適化を進めても一般的な文字列の圧縮率でDAに追いつけるほどの向上は難しいだろう)。DAはノーリスクゆえデフォルトで使用できることを目的に作られているが単語、数値、識別子のような単純な文字列またはその組み合わせであれば多くの用途においてハフマン符号より優れた最適な圧縮エンコーディングとしてそのまま使い続けられるだろう(要するにずぼらエンコーディングということである。汎用エンコーディングなので特定領域に特化(ランレングスなど)または独自に符号化したもの(Protobufのフィールド番号など)には当然DAもハフマン符号も敵わない)。メモリフットプリントも約1KBと小さい。(その後改良によりすべての圧縮率が20%以上となり欠点のない万能の汎用圧縮エンコーディングとなった)

理論的観点から見ると汎用的な静的テーブルを使用するハフマン符号はランダム文字列も圧縮できるほど全体的かつ平均的に圧縮率を高めたことで反面最も圧縮頻度の高い単語、数値、識別子(HEX)などの部分的な圧縮率が低下していると考えられる(万能を追求しすぎて器用貧乏化した。そのうえ肥大化リスクもあるので逆に汎用エンコーディングとしてはバランスが悪く使いにくいものとなった。ハフマン符号は個別の符号化では最適に近くとも個別の偏りの情報を持たない汎用的な非個別的符号化では個別の偏りに動的に適応するアルゴリズムより圧縮率が低くなりうることは自明である。DAは次の部分文字列と文字の2つの頻度情報を持つがハフマン符号は一般的かつ全体的な頻度情報しか持たないため基本的に部分文字列の規則性が高いほどDAに有利となる)。これは文字レベルの最適化と文字列レベルの最適化の違いと考えられハフマン符号は文字レベルの圧縮エンコーディング、DAは文字列レベルの圧縮エンコーディングと言える。上記圧縮率の比較は規則性の高い部分文字列の多い文字列の圧縮には文字列レベルのエンコーディングの方が文字レベルのエンコーディングより適していることを示している。DAが最終的に単語や数値等の部分文字列の多い文字列においてもハフマン符号の圧縮率を超えられなかったとしても部分文字列によってはランレングスや独自符号などハフマン符号より優れた圧縮方式が存在することから部分文字列ごとに最適な圧縮方式を適用し全体として複数の圧縮方式を組み合わせる複合方式の圧縮率がハフマン符号より高くなりうることは自明である。DAはこれを可能にする効率的な合成方法を開発したものでもある。複合方式は少なくとも大文字小文字の各文字列両方の圧縮において非常に短い文字列を除いてハフマン符号より理論的に優れていることを容易に証明できる。すべての大文字小文字に5ビットの符号を割り当てることは単一の符号表しか持たないハフマン符号では不可能だが複数の符号表を複合できる複合方式では容易である。符号表が2つあれば符号表自体が1ビットの情報となるため符号のビット数を平均1ビット削減できる。この差は文字数に比例して拡大することはあっても縮小することはない。従ってこの場合に単一の静的テーブルを使用するハフマン符号より複合方式の方が効率的で圧縮率が高いことが理論的に証明される。程度の差はあれど識別可能なすべての規則的文字列に同じことが当てはまり理想的なハフマン符号であってもこの理論的非効率性を免れることはない。これはハフマン符号に限らず算術符号や範囲符号においても同じである。なお文字列内での符号表の変更はヘッダや文字数などのオーバーヘッドなしで可能である。

ここまで読めば複合方式のハフマン符号の圧縮率を知りたいと思っただろう。これはヘッダや文字数などのオーバーヘッドなしで合成できることもあり確かにDAとHPACKより圧縮率が高いことも多い。次は圧縮率の完全な比較である。

'Huffman comp. ratio random number', 0.46875, 1.8823529411764706
'Delta   comp. ratio random number', 0.422590625, 1.7318735082886383
'HPACK   comp. ratio random number', 0.27509062500000003, 1.3794827801751082
'SimH2E5 comp. ratio random number', 0.46875, 1.8823529411764706
'SimH3E5 comp. ratio random number', 0.46875, 1.8823529411764706
'SimH2S5 comp. ratio random number', 0.46875, 1.8823529411764706
'SimH3S5 comp. ratio random number', 0.46875, 1.8823529411764706
'SimH2S0 comp. ratio random number', 0.46875, 1.8823529411764706

'Huffman comp. ratio random hex', 0.421784375, 1.7294586254046662
'Delta   comp. ratio random hex', 0.304153125, 1.4370977810312076
'HPACK   comp. ratio random hex', 0.25192812499999995, 1.3367699460696876
'SimH2E5 comp. ratio random hex', 0.019862500000000005, 1.0202650138373444
'SimH3E5 comp. ratio random hex', -0.040043749999999934, 0.961498013905665
'SimH2S5 comp. ratio random hex', 0.14002812499999995, 1.1628287262301455
'SimH3S5 comp. ratio random hex', 0.14002812499999995, 1.1628287262301455
'SimH2S0 comp. ratio random hex', 0.18818437499999996, 1.2318067911048152

'Huffman comp. ratio random 36', 0.09043749999999995, 1.0994296708582423
'Delta   comp. ratio random 36', 0.06517968750000003, 1.0697242952773345
'HPACK   comp. ratio random 36', 0.25349999999999995, 1.3395847287340925
'SimH2E5 comp. ratio random 36', 0.05402343750000005, 1.0571086426890202
'SimH3E5 comp. ratio random 36', 0.0036562500000000275, 1.0036696672207759
'SimH2S5 comp. ratio random 36', 0.15463281250000005, 1.1829179258273494
'SimH3S5 comp. ratio random 36', 0.15463281250000005, 1.1829179258273494
'SimH2S0 comp. ratio random 36', 0.1783828125, 1.2171118316582197

'Huffman comp. ratio random 64', 0.22778906249999997, 1.2949829527634733
'Delta   comp. ratio random 64', 0.17917968750000002, 1.2182934373958978
'HPACK   comp. ratio random 64', 0.188125, 1.2317167051578137
'SimH2E5 comp. ratio random 64', -0.17171874999999992, 0.8534471262835045
'SimH3E5 comp. ratio random 64', -0.25217187499999993, 0.7986124109359987
'SimH2S5 comp. ratio random 64', -0.010890625000000043, 0.9892267029383125
'SimH3S5 comp. ratio random 64', -0.010890625000000043, 0.9892267029383125
'SimH2S0 comp. ratio random 64', 0.09820312499999995, 1.1088971671142684

'Huffman comp. ratio word 3-6', 0.27659305355290786, 1.3823477987201456
'Delta   comp. ratio word 3-6', 0.2918974981659963, 1.412224921406116
'HPACK   comp. ratio word 3-6', 0.21294680124459286, 1.2705621444412303
'SimH2E5 comp. ratio word 3-6', 0.2741392830942805, 1.3776747752143306
'SimH3E5 comp. ratio word 3-6', 0.2741139864916142, 1.377626764244642
'SimH2S5 comp. ratio word 3-6', 0.2740128000809491, 1.3774347538241751
'SimH3S5 comp. ratio word 3-6', 0.2740128000809491, 1.3774347538241751
'SimH2S0 comp. ratio word 3-6', 0.14601199058966385, 1.1709766284546343

'Huffman comp. ratio word 5-10', 0.2896344764644918, 1.4077259760904122
'Delta   comp. ratio word 5-10', 0.3177409624576546, 1.4657189498027479
'HPACK   comp. ratio word 5-10', 0.2369947561371757, 1.3106069821189636
'SimH2E5 comp. ratio word 5-10', 0.28957260197688983, 1.4076033705663336
'SimH3E5 comp. ratio word 5-10', 0.28955713335498945, 1.4075727225222088
'SimH2S5 comp. ratio word 5-10', 0.2894333843797856, 1.4073275862068966
'SimH3S5 comp. ratio word 5-10', 0.2894333843797856, 1.4073275862068966
'SimH2S0 comp. ratio word 5-10', 0.22670812257335993, 1.2931727710987977

'Huffman comp. ratio word 1', 0.3017784799236677, 1.4322102244724226
'Delta   comp. ratio word 1', 0.32395864291188936, 1.479199444701527
'HPACK   comp. ratio word 1', 0.2422142622514899, 1.3196342319283325
'SimH2E5 comp. ratio word 1', 0.3017002706042452, 1.4320498174405842
'SimH3E5 comp. ratio word 1', 0.3017002706042452, 1.4320498174405842
'SimH2S5 comp. ratio word 1', 0.3012935821432482, 1.4312162797465804
'SimH3S5 comp. ratio word 1', 0.3012935821432482, 1.4312162797465804
'SimH2S0 comp. ratio word 1', 0.2352223490951182, 1.3075695907389606

'Huffman comp. ratio word 2', 0.340729472273534, 1.5168280060213826
'Delta   comp. ratio word 2', 0.2984751349197725, 1.4254662233328514
'HPACK   comp. ratio word 2', 0.2732514759679815, 1.375991786611379
'SimH2E5 comp. ratio word 2', 0.3424173276830019, 1.5207213360359566
'SimH3E5 comp. ratio word 2', 0.34238835162447023, 1.5206543291473893
'SimH2S5 comp. ratio word 2', 0.2520337571081893, 1.3369587324339245
'SimH3S5 comp. ratio word 2', 0.2520337571081893, 1.3369587324339245
'SimH2S0 comp. ratio word 2', 0.3073345648158209, 1.4436984281366674

'Huffman comp. ratio word 4', 0.3570663474261231, 1.5553704429635438
'Delta   comp. ratio word 4', 0.3330567982133731, 1.4993780539649715
'HPACK   comp. ratio word 4', 0.28805858344009694, 1.4046099534874574
'SimH2E5 comp. ratio word 4', 0.35931713327592607, 1.560834621835884
'SimH3E5 comp. ratio word 4', 0.3592751279412485, 1.5607322949503117
'SimH2S5 comp. ratio word 4', 0.22777392728876567, 1.2949575718015667
'SimH3S5 comp. ratio word 4', 0.22777392728876567, 1.2949575718015667
'SimH2S0 comp. ratio word 4', 0.3419794313877863, 1.519709333872392

'Huffman comp. ratio word 6', 0.3620691642252736, 1.567568055846624
'Delta   comp. ratio word 6', 0.3441845670148005, 1.524819255088448
'HPACK   comp. ratio word 6', 0.2926721326212379, 1.4137715281964383
'SimH2E5 comp. ratio word 6', 0.3644755979780424, 1.5735037031126458
'SimH3E5 comp. ratio word 6', 0.3644087525960211, 1.5733382171079593
'SimH2S5 comp. ratio word 6', 0.22031315908970417, 1.282566214446412
'SimH3S5 comp. ratio word 6', 0.22031315908970417, 1.282566214446412
'SimH2S0 comp. ratio word 6', 0.353072697810468, 1.5457687387987644

'Huffman comp. ratio word 8', 0.3644927162341125, 1.5735460875825096
'Delta   comp. ratio word 8', 0.34956916567772556, 1.5374424877042678
'HPACK   comp. ratio word 8', 0.2947749514128958, 1.417987069522655
'SimH2E5 comp. ratio word 8', 0.3670570833978295, 1.579921306913905
'SimH3E5 comp. ratio word 8', 0.3670072063705003, 1.5797968161155957
'SimH2S5 comp. ratio word 8', 0.21643878024869723, 1.2762244669502574
'SimH3S5 comp. ratio word 8', 0.21643878024869723, 1.2762244669502574
'SimH2S0 comp. ratio word 8', 0.3583647214626008, 1.558517795778763

'Huffman comp. ratio word 1 upper', -0.006710359606450611, 0.9933343691733997
'Delta   comp. ratio word 1 upper', 0.2063318265004458, 1.2599724083563264
'HPACK   comp. ratio word 1 upper', 0.0559196633870892, 1.0592318907813638
'SimH2E5 comp. ratio word 1 upper', 0.17357776352630183, 1.2100352046030964
'SimH3E5 comp. ratio word 1 upper', 0.1453285573508939, 1.170040263543192
'SimH2S5 comp. ratio word 1 upper', 0.20617540786160082, 1.2597241379310344
'SimH3S5 comp. ratio word 1 upper', 0.20617540786160082, 1.2597241379310344
'SimH2S0 comp. ratio word 1 upper', 0.17534529414525035, 1.2126287437643444

'Huffman comp. ratio word 1 camel', 0.18318186795138514, 1.2242627345844503
'Delta   comp. ratio word 1 camel', 0.2663183744975052, 1.3629890203603028
'HPACK   comp. ratio word 1 camel', 0.21825092678043512, 1.279182840449798
'SimH2E5 comp. ratio word 1 camel', 0.026825796561918303, 1.0275652565256526
'SimH3E5 comp. ratio word 1 camel', -0.010949304719150232, 0.9891692840896783
'SimH2S5 comp. ratio word 1 camel', 0.1149989832788475, 1.129942204704926
'SimH3S5 comp. ratio word 1 camel', 0.1149989832788475, 1.129942204704926
'SimH2S0 comp. ratio word 1 camel', 0.12571366003973028, 1.143790031130354

'Huffman comp. ratio text 100', 0.36971310263235724, 1.5865790708587517
'Delta   comp. ratio text 100', 0.35245982450951396, 1.544305724725944
'HPACK   comp. ratio text 100', 0.2929113674455289, 1.414249860568879
'SimH2E5 comp. ratio text 100', 0.3682342502218279, 1.5828651685393258
'SimH3E5 comp. ratio text 100', 0.36793847973972194, 1.582124473561067
'SimH2S5 comp. ratio text 100', 0.3692201518288475, 1.5853391684901532
'SimH3S5 comp. ratio text 100', 0.3692201518288475, 1.5853391684901532
'SimH2S0 comp. ratio text 100', 0.3615301192940944, 1.5662445954292774

'Huffman comp. ratio text 500', 0.3732724408192569, 1.5955896391522943
'Delta   comp. ratio text 500', 0.35289073250503555, 1.5453340729783038
'HPACK   comp. ratio text 500', 0.2964122609337295, 1.4212868480725624
'SimH2E5 comp. ratio text 500', 0.3719960911792274, 1.5923467767545252
'SimH3E5 comp. ratio text 500', 0.37159723191671823, 1.591336083782926
'SimH2S5 comp. ratio text 500', 0.3724148934048621, 1.5934093870157933
'SimH3S5 comp. ratio text 500', 0.3724148934048621, 1.5934093870157933
'SimH2S0 comp. ratio text 500', 0.3686855593004008, 1.5839967146828406

'Huffman comp. ratio text 1000', 0.3735506486502681, 1.5962982447749774
'Delta   comp. ratio text 1000', 0.35317733768762916, 1.5460188058733615
'HPACK   comp. ratio text 1000', 0.29711078487181797, 1.422699308051889
'SimH2E5 comp. ratio text 1000', 0.3723522185936423, 1.5932502744761086
'SimH3E5 comp. ratio text 1000', 0.37209255874804004, 1.5925914144386302
'SimH2S5 comp. ratio text 1000', 0.37293145978767817, 1.5947220054468139
'SimH3S5 comp. ratio text 1000', 0.37293145978767817, 1.5947220054468139
'SimH2S0 comp. ratio text 1000', 0.3689866275179515, 1.5847524689794885

'Huffman comp. ratio country', 0.208587786259542, 1.2635640221847118
'Delta   comp. ratio country', 0.30586832061068703, 1.4406488418448002
'HPACK   comp. ratio country', 0.23847805343511452, 1.3131597907464838
'SimH2E5 comp. ratio country', 0.05405534351145036, 1.0571442981792505
'SimH3E5 comp. ratio country', -0.002934160305343436, 0.9970744238042004
'SimH2S5 comp. ratio country', 0.13188215648854962, 1.151917343335669
'SimH3S5 comp. ratio country', 0.13188215648854962, 1.151917343335669
'SimH2S0 comp. ratio country', 0.130462786259542, 1.1500370360209597

'Huffman comp. ratio sample', 0.36345381526104414, 1.5709779179810726
'Delta   comp. ratio sample', 0.3544176706827309, 1.5489891135303266
'HPACK   comp. ratio sample', 0.29518072289156627, 1.4188034188034189
'SimH2E5 comp. ratio sample', 0.3644578313253012, 1.5734597156398105
'SimH3E5 comp. ratio sample', 0.3624497991967871, 1.568503937007874
'SimH2S5 comp. ratio sample', 0.3654618473895582, 1.5759493670886076
'SimH3S5 comp. ratio sample', 0.3654618473895582, 1.5759493670886076
'SimH2S0 comp. ratio sample', 0.35843373493975905, 1.5586854460093897

'Huffman comp. ratio json', 0.2314814814814815, 1.3012048192771084
'Delta   comp. ratio json', 0.17592592592592593, 1.2134831460674158
'HPACK   comp. ratio json', 0.16666666666666663, 1.2
'SimH2E5 comp. ratio json', 0.15740740740740744, 1.1868131868131868
'SimH3E5 comp. ratio json', 0.12962962962962965, 1.148936170212766
'SimH2S5 comp. ratio json', 0.2129629629629629, 1.2705882352941176
'SimH3S5 comp. ratio json', 0.2129629629629629, 1.2705882352941176
'SimH2S0 comp. ratio json', 0.18518518518518523, 1.2272727272727273

かなり大雑把な符号化しかしてないため圧縮率が低いものも適切に符号化すればいくつかは有意に改善できるだろう。しかし文字列レベルの圧縮エンコーディングに近づいたことでhttpヘッダに多い断片的文字列の圧縮に不利になったため最終的にHPACKの上位互換にもなるかは厳しいところである。DAに対してもハフマン符号の性質として短文字列の圧縮率が低い傾向が残り大文字小文字の圧縮率の両立も依然として難しい。そしてこのような一長一短に近い性能が複数のハフマン符号の使用により10−20倍に増加したフットプリント10-20KBに釣り合うかも微妙なところである。以上のことからDAは単純ながらバランスがよく一般にハフマン符号より優れた圧縮エンコーディングとして選択できる。ただし実装としては実験的に作っただけで安定性は全く保証していないので永続化や通信に使うならバージョンを固定して使う必要がある。揮発性データなら整合性を考慮しなくてよいので問題ない。

さて最後に前述の理論でHPACKの上位互換エンコーディングを作れることを実証しよう。大文字小文字トークンの3種類のハフマン符号表を複合するだけである。フットプリントもたぶん素朴に作っても3-4倍程度でそう大きくないし最適化すればたぶん一つの符号表の補正として残りの符号表を表現して2倍以下に抑えられる。サンプルはgoogle.comのhttpヘッダである。

'XPACK   comp. ratio request', 0.2533415841584158, 1.3393005138405436
'HPACK   comp. ratio request', 0.2471534653465347, 1.3282919612033537
'Delta   comp. ratio request', 0.19801980198019797, 1.2469135802469136
0, 'accept'
0, 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7'
0, 'accept-encoding'
0, 'gzip, deflate, br'
0, 'accept-language'
0, 'ja,en-US;q=0.9,en;q=0.8'
0, 'cache-control'
0, 'max-age=0'
0, 'dnt'
0, '1'
0, 'sec-ch-ua'
-1, '"Google Chrome";v="117", "Not;A=Brand";v="8", "Chromium";v="117"'
0, 'sec-ch-ua-arch'
0, '"x86"'
0, 'sec-ch-ua-bitness'
0, '"64"'
0, 'sec-ch-ua-full-version'
0, '"117.0.5938.89"'
0, 'sec-ch-ua-full-version-list'
-1, '"Google Chrome";v="117.0.5938.89", "Not;A=Brand";v="8.0.0.0", "Chromium";v="117.0.5938.89"'
0, 'sec-ch-ua-mobile'
0, '?0'
0, 'sec-ch-ua-model'
0, '""'
0, 'sec-ch-ua-platform'
0, '"Windows"'
0, 'sec-ch-ua-platform-version'
0, '"10.0.0"'
0, 'sec-ch-ua-wow64'
0, '?0'
0, 'sec-fetch-dest'
0, 'document'
0, 'sec-fetch-mode'
0, 'navigate'
0, 'sec-fetch-site'
0, 'same-origin'
0, 'sec-fetch-user'
0, '?1'
0, 'sec-gpc'
0, '1'
0, 'upgrade-insecure-requests'
0, '1'
0, 'user-agent'
-3, 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36'
0, 'x-client-data'
-45, 'CKa1yQEIj7bJAQiltskBCKmdygEI5tTKAQieicsBCJahywEIhaDNAQjwsc0BCNy9zQEI38TNAQi1xc0BCLnKzQEI1dDNAQiR0s0BCIrTzQEIwtTNAQjJ1s0BCPnA1BUYwcvMARi4v80B'

'XPACK   comp. ratio response', 0.25389886578449905, 1.340300870942201
'HPACK   comp. ratio response', 0.24155245746691867, 1.3184827478775605
'Delta   comp. ratio response', 0.20510396975425327, 1.258026159334126
0, 'accept-ch'
-2, 'Sec-CH-UA-Arch'
0, 'accept-ch'
-2, 'Sec-CH-UA-Bitness'
0, 'accept-ch'
-2, 'Sec-CH-UA-Full-Version'
0, 'accept-ch'
-2, 'Sec-CH-UA-Full-Version-List'
0, 'accept-ch'
-2, 'Sec-CH-UA-Model'
0, 'accept-ch'
-2, 'Sec-CH-UA-Platform'
0, 'accept-ch'
-2, 'Sec-CH-UA-Platform-Version'
0, 'accept-ch'
-1, 'Sec-CH-UA-WoW64'
0, 'alt-svc'
0, 'h3=":443"; ma=2592000,h3-29=":443"; ma=2592000'
0, 'cache-control'
0, 'private, max-age=0'
0, 'content-encoding'
0, 'br'
0, 'content-length'
0, '54188'
0, 'content-security-policy-report-only'
-2, 'object-src 'none';base-uri 'self';script-src 'nonce-OqX2tRcsQ42YI77KwfGMfg' 'strict-dynamic' 'report-sample' 'unsafe-eval' 'unsafe-inline' https'
0, 'http:;report-uri https://csp.withgoogle.com/csp/gws/other-hp'
0, 'content-type'
-1, 'text/html; charset=UTF-8'
0, 'cross-origin-opener-policy'
0, 'same-origin-allow-popups; report-to="gws"'
0, 'date'
-2, 'Wed, 22 Nov 2023 18:46:19 GMT'
0, 'expires'
0, '-1'
0, 'origin-trial'
-50, 'Ap+qNlnLzJDKSmEHjzM5ilaa908GuehlLqGb6ezME5lkhelj20qVzfv06zPmQ3LodoeujZuphAolrnhnPA8w4AIAAABfeyJvcmlnaW4iOiJodHRwczovL3d3dy5nb29nbGUuY29tOjQ0MyIsImZlYXR1cmUiOiJQZXJtaXNzaW9uc1BvbGljeVVubG9hZCIsImV4cGlyeSI6MTY4NTY2Mzk5OX0='
0, 'origin-trial'
-83, 'AvudrjMZqL7335p1KLV2lHo1kxdMeIN0dUI15d0CPz9dovVLCcXk8OAqjho1DX4s6NbHbA/AGobuGvcZv0drGgQAAAB9eyJvcmlnaW4iOiJodHRwczovL3d3dy5nb29nbGUuY29tOjQ0MyIsImZlYXR1cmUiOiJCYWNrRm9yd2FyZENhY2hlTm90UmVzdG9yZWRSZWFzb25zIiwiZXhwaXJ5IjoxNjkxNTM5MTk5LCJpc1N1YmRvbWFpbiI6dHJ1ZX0='
0, 'p3p'
-2, 'CP="This is not a P3P policy! See g.co/p3phelp for more info."'
0, 'permissions-policy'
0, 'unload=()'
0, 'report-to'
0, '{"group":"gws","max_age":2592000,"endpoints":[{"url":"https://csp.withgoogle.com/csp/report-to/gws/other"}]}'   
0, 'server'
0, 'gws'
0, 'set-cookie'
0, '1P_JAR=2023-11-22-18; expires=Fri, 22-Dec-2023 18:46:19 GMT; path=/; domain=.google.com; Secure; SameSite=none' 
0, 'set-cookie'
-23, 'AEC=Ackid1QH6gVXB6Rn68KWRmRtOGSW1unAfUHYsxuZh3Zs8cyWCZdKy8vrhQ; expires=Mon, 20-May-2024 18:46:19 GMT; path=/; domain=.google.com; Secure; HttpOnly; SameSite=lax'
0, 'set-cookie'
-19, 'NID=511=fx_DiN-XffVTX7QHZe7UgP5GQd0mx2HY9B0Hz6MgzEpOESnD8DldcSLyj-U6AHIo8t4-dcOKelciAyOK2j03GJE1r_31zKvXnECnKWvOQiFPO6mtTTaCZWqtn2x8m5lnzbB_CyUA-HzXz-Vw3TXC0eeW_AQlcu8CybBgyxtW5Kc; expires=Thu, 23-May-2024 18:46:19 GMT; path=/; domain=.google.com; Secure; HttpOnly; SameSite=none'
0, 'strict-transport-security'
0, 'max-age=31536000'
0, 'x-frame-options'
-12, 'SAMEORIGIN'
0, 'x-xss-protection'
0, '0'

理論的に肥大化する可能性がないではないが全体として肥大化する可能性は低くこのサンプルではフィールド単位でもまったく肥大化していない。約1%圧縮率が向上しているがトークンの圧縮効果が大きいためログインしてトークンが増えるほどさらに圧縮率が上がる。セキュリティ上の必要性からトークンによりヘッダサイズが増大しがちな昨今の需要に応える圧縮エンコーディングである。

github.com

アーマードコア6はいかに前作から退化したか

購入者として知ることを明らかにする。至る所に技術の喪失が垣間見える。

機動力の喪失

壁蹴り(ブーストドライブ)がなくなったことによりACVIの機動性と戦闘速度はACVから比較するのもおこがましいほど低下した。まず壁蹴りによりEN消費なし(消費より回復のほうが多い)で高度を保つことができなくなり高所の有利を得て戦闘を開始する三次元戦闘の自由度が低下した。水平移動においても壁蹴りによりEN消費なしで高速移動できないためENを温存しながらまたは温存せずに直ちに戦闘に突入することも緊急離脱することもできなくなった。交戦後も壁蹴りによる空中でのEN回復ができなくなったためEN枯渇を避けるために接地を維持した地上戦闘が主体となり地面にへばりついた平面的な二次元戦闘が主体とならざるをえなくなった。つまりACVIは前作ACVの三次元戦闘から二次元戦闘に退化している。ACVIのACは地面に縛られているも同然である。上手いブルマグ戦を見れば明らかなようにACV(D)ではほとんど地面に落ちず空中で戦闘し続けることができており戦闘時間のほとんどが空中での三次元高速高機動戦闘で占められている(ACVIでもアセンを詰めれば浮き続けることはできるがこれが標準ではなくQBする余裕もほとんどないためほぼクラゲのように浮きながら戦ってるだけであり高速高機動戦闘には程遠い)。浮遊できないACVより浮遊できるACVIのほうが地面に縛られているとはなんとも奇妙な感がある。戦闘機動においても壁蹴りによる切り返しにより敵と交差し側背を取る高速機動戦とこれによる機動による火力差の逆転が不可能になった。ACVの軽中量機の中級者以上の戦闘は領地戦のほとんどがこのような交差射撃であり(重量機と正面から撃ち合って勝てるわけないのだから当然である。同格でも不確実だし勝てても残敵に勝つ余裕が残らない)ランクマでさえ毎回のように使われる必須技能である(これができず引き撃ちされて負けるやつがいたらそいつが雑魚すぎるだけ)。全体としてACVIの機動性と戦闘速度はACVの1/10以下だろう。FAとVの間とか言ってたけどVの10倍遅いのなんで制作側がわからないかな。これほど戦術性も機動性も劇的に退化され戦闘技術の見せようがなくなってはモチベーションを保つ方法を見つけるのは難しい。ACVIの対人戦に技術を見いだせるとすれば1ターンでハメ殺すアセンとコンボの組み立てくらいだろう。

カニズムを失ったメカ

ACVIは機動力の喪失を許容できるようボスの射撃をあまり被弾しないようおよびまたは被弾してもよいよう雑魚並みに弱体化し小さな移動量で避けられる斬撃を主力とするよう主客転倒したものになっているFCSの誘導が避ける必要がないかQB1回程度の短距離移動で避けられる程度のものになっておりFCSを装備している意味がなくなっているのである。これは明らかにFCSを装備した兵器の戦い方ではない。ACVIのボスはFCSの有用性を解さず利用していないせいで退化し弱体化しているのである。AC未満の命中率に雑魚並みの低威力の産廃射撃武器と短距離ブースト1回で避けられる斬撃武器を装備しFCSを活かせないC兵器は有利な機体で不利な戦い方しかできない欠陥品ということである。この結果ACVIはACもボスも銃を持ってるが銃が欠陥品だから銃剣で戦ったほうが強いという状況でありもちろん欠陥銃を渡して銃剣突撃させるほうが悪い旧日本軍かお前はコア理論などとのたまい銃剣突撃を強いる様など鬼畜牟田口の再来を思わせ感極まる(言うまでもなく銃剣の間合いの近接戦闘という意味である。まあACとボス自体が弱い銃と強い剣を一体化した銃剣のようなものである。ミサイラーのような通常なら明らかにナーフされる例外を除きメインウェポンの銃が弱いので銃剣突撃させてサブウェポンの剣で白兵戦させる以外運用方法がない)。このように旧日本軍並みに知能が退化したフロ牟田口は見るに堪えない。仮にFCSが新技術で代替されていたとしても旧技術に劣るこれらの欠陥を抱えていい理由にはならず旧技術に劣る失敗した新技術であるだけである。端的に言ってACVIのボスの隙だらけの斬撃より距離を保ったオトキャタンクのほうがよほど強いわかってしまえば対処しやすいのがゲームの偽物の難易度でありわかっていても対処しにくいのが合理的な本物の難易度である。そしてACVIは技術的合理性の帰結により明らかになった本物の難易度から逃げた高度な科学技術を基盤とするアーマードコアで科学に反してソウルライクな剣と魔法の難易度をどれほど上げたところで技術的合理性のない偽物の難易度にしかならないのである(そんなに射撃武器を弱体化させたければミノフスキー粒子でも持ってこい)。ACVIの戦闘は機動や遮蔽物などによりFCSの照準から逃れロックを外す、FCSの支援を受けた機械同士の高度な戦闘が失われ生身の生物がする文明水準の低いの原始的な戦闘に成り下がっている。高度な兵器の優位性を生み出しているメカニズムを理解せずFCSが効果のない形だけのものになっているのである。すなわちフロムはメカニズムの備わったメカを作る技術を失いカーゴカルトのハリボテのメカしか作れなくなったのである。メカならざる生物でもない限り生物のように戦うソウルライクなアーマードコアはメカニズム的に不可能なのである。

EN回復手段の欠如

ENを回復するには停止か徐行して回復を待たなければならないがACVIの対戦はほぼ開所なのでこのような行動は自殺行為となる(射線切れるのは宇宙港とザイオンくらいか)。すなわち先にENが切れた方が死ぬ。ACVではQBより何倍も移動距離の大きい壁蹴りが使い放題なのにACVIではABとQBの使用が抑制され低速で戦闘するよう強力な圧力がかかっているのである。ところでハメ技で簡単に倒せることはよくあることだが本来のゲーム性である機動と射撃(ミサイル含む)で倒すこととあまりに難易度の差が大きすぎる今作のゲーム性とはなんなのか。どちらが本当のゲーム性なのか。自分は攻略情報を見ず完全に独力で射撃主体でクリアしたが半数以上の人が近接コンボで格ゲー的にしかクリアできないならそれはもう格ゲーではないか(格ゲーは例えだが主に近接のコンボゲーなのは間違いない)。対人戦はもはやサッカーゲームと化している。また下手な人がレベル上げでクリアできない代わりの救済策としてハメ技を用意したのかもしれないがレベル上げやアイテム入手のような代わりの相応の時間をかけず純粋に劇的なショートカットを容易に可能にしているのは攻略法を歪めていないか。コストの低すぎる救済策を常設したせいで攻撃に対し用意された避け方と反撃を繰り返し用意された手順通りに倒す正攻法が単なる馬鹿な遠回りになっていないか。せめて救済武器は2つ目を法外な値段にするのがよかったかもしれない。それが目印にもなる。ともあれEN切れ後もACVでは壁蹴りでENを回復しながら無限に逃げられるので技術さえあれば容易に緊急離脱できたがACVIには緊急離脱もこれに代わるEN回復手段もないのでENが切れる前に有利を取れなければそのままなぶり殺しになる。逃げ切れず硬直を取られるのも速度差をENで補えなかった結果である。このようにACVIは戦いながらEN回復ができず離脱もできないせいで継戦能力が著しく低下している(だからチーム戦で横殴りが異常に容易で強いのである。シングルであろうと敵猛攻の中ではEN回復時間はPAで稼ぐしかない)。このためACVIの対人戦は基本的に先にENが切れたほうが死ぬ実質1ターンしかないあまりに単純すぎるゲームとなっている

スタッガーとかいうクソゴミ

スタッガーとは要するに最後のポイント10倍のクイズ番組である。これにより途中までコツコツ貯めたポイントがボーナス問題の勝敗で無駄になる偶然性が高く実力差の反映率の低い非常に大味な対戦となる。ボーナス問題でラグればさらに倍率ドン!より正確に言えばアセンという任意のボーナス問題の取りやすさと倍率をぶつけ合ってるようなものである。ACVIに観戦機能が充実しているのはその興行性の高さを的確に捉えた慧眼であったと言える。博打的という意味で。

お見合いの如き超低速戦闘

距離を取るのが困難、リロードが長い(時間占有率が大きい)など行動の制約が強く自由度が低いためお互い至近距離で弾(リロード等)もENも切れて敵が目の前にいるのに何もできず低速でうろうろするしかない非常に間抜けな状況が多発する。こんな間抜けなゲームは他にないだろう。装弾数が少なくリロードが長いのはおそらくスタッガー中に無計画に容易にダメージが入りすぎないようにするためでありスタッガーがなければ装弾数が多くリロードの短いハイテンポな高速戦闘ができただろう。スタッガーという欠陥システムの欠陥を埋め合わせるために戦闘が遅く退屈で間抜けになっているのである。

ベイブレード的強制接近戦

ACVIは高速接近はABにより効率的に行えるが高速離脱はQBにより非効率にしか行えないよう接近に強い勾配がかかっている。これは要するにベイブレードのように接触するまで接近していくフィールドで戦わされているということである。運動効率的に互いに敵を中心にすり鉢状になっているイメージで正しい。内側への回避を強制するミサイルがさらにこれを加速する。ACVIのACはベイブレードである。実際初期レギュレーションでは四脚がベイブレードのように回っていた。そうでなくなった後もプレイヤーは互いにグルグル回っている。遮蔽物がないと移動方向を切り替える余裕を得難く遮蔽物から遮蔽物へ移動していかなければ行動パターンに複雑性が生まれないのである。そしてACVIは遮蔽物の多いマップこそあるもののQBの低い機動力とENの制限から遮蔽物を利用する機動が緩慢で苦痛であるためほとんどのプレイヤーは遮蔽物があっても使わず開所で戦うことを好む。遮蔽物はただ置いておけばよいというものではない。遮蔽物から遮蔽物へ移動する行動の選択の多様性と組み合わせの複雑性が欠如したゲームデザインがACVIの対人戦が単調で退屈である最大の原因だろう。これはACVのデブリーフィングで見れる移動経路を比較すれば極めて顕著に視認できるだろう。ACVは移動方向を頻繁に切り返す複雑な機動で広いマップを大きく移動しているのに対してACVIは狭いマップをろくに動けずほとんどの時間ベイブレードのようにグルグル回ってるだけである。時折回転方向が変わるところもベイブレードそっくりである。ソウルライクでは通路により円運動が抑制されているためこの問題はフロムの中でもACVIが頭抜けて最悪なものとなっている。遮蔽物や隠蔽物などの障害物がない問題は一般的なFPS/TPSと比較すると明確である。障害物がありこれらを駆使して移動するのが当然のFPSから障害物を撤去し丸見えの敵と正面から撃ち合うだけのFPSがどれほど単調で退屈か想像するだけでうんざりするだろう。ACVIの対人戦とはまさに障害物がなく丸見えの敵と正面から撃ち合うだけのFPS(のTPS)でありこれにより対人戦のゲームデザインが絶対的に著しく劣っていると断定できるのである。ACVでは一般的FPS同様障害物豊富であるに加え高速機動による回避の選択肢が追加されているぶん選択肢豊富で一般的FPSより優れたゲームデザインであったと言える。

遮蔽物の欠如とAIの稚拙さ

ACVIの対戦ステージは有用な遮蔽物がほとんどないうえ戦場が狭く制限されている。このためACVIの対人戦はほぼ開所で火力をぶっぱしてDPSレースするだけの非常に単調な戦闘となっている。ボス戦においても遮蔽物はすべて破壊可能オブジェクトであり遮蔽物を考慮したルーチンになっていないことを示している。ACVIのAIは破壊不能な遮蔽物を駆使していたACVから無惨なまでに退化しているのである。どいつもこいつも更地か更地にしたフィールドで大技ぶっぱして大火力を垂れ流すだけ。障害物を考慮しないAIなど最も単純で初歩的なAIである。しかも銃火器主体のゲームなのに主力が斬撃で射撃は飾り。プレイヤーと同じ装備できっちり遮蔽物駆使しまくって機動と射撃で高難易度実現したブルマグ見習え粗製共

これは何のゲームだ?

ACVがフルオート射撃の射撃戦が標準だったのと対照的にACVIのトップアセンはひたすら正面から蹴り合うものや手動で高速連射するものが多い。これは何のゲームだ?俺はハイスピードメカアクションという触れ込みのゲームを買ったのだ。サッカーゲームも手動でフルオート射撃を再現する腕を競うゲームも買っていない(未来の銃器にもかかわらずフルオート射撃できないなど荒唐無稽も甚だしい)。ハイスピードメカアクションとして売り込みながら勝つためにサッカーや手動フルオート射撃の腕を競わせるゲームとそのメーカーはプレイヤーを侮辱している。馬鹿みたいに正面から蹴り合う塩試合に帰着するゲームがつまらないことは言うまでもない。ACVI最大の癌はAB重ショ(とこれにかかるバフ)と重ショキックコンボループである。AB重ショの当てやすすぎる超衝撃でスタッガーを取るのが簡単すぎて他の武器と戦術が食われておりAB重ショキックキックのループも火力もDPSが高すぎてこれもクールタイムがありコンボ火力も低い他の武器と戦術で苦労するのが馬鹿みたいになっている。特に蹴りの怯みで相手の行動をキャンセルできるのが強すぎるせいで近づいた後はずっと蹴り合いになってしまい他の行動が蹴りより優秀になる機会が少ないので他の行動を挟む隙を見つけることすら難しい。蹴りの怯みを消して蹴りあいにならないようにすべきである。重ショキックコンボループには欠点となるトレードオフがまったくない。ACVIでは一応超高速コンボを作れるが当てやすさも火力も歯牙にもかからない弱さでやりがいのある面白い戦いはできない(チームならパルブレコンボアセンは結構強力である。パルブレ単体のアシストキル能力が高いので)。

妙な硬直が多いし反応が遅すぎる

両手同時撃ちはできるが次にリロード完了と同時に撃つと片方しか発射されないのでずらして撃たなければならない。他にも左盾右の順に撃つと干渉しないはずの盾が展開しないなど多くの異常動作がありいつ正常動作していつしないか把握も管理もしきれない。もはや意図的な制限でなく制限の管理に失敗しただけに見える。意図的でもQB後に0.4秒ほど盾を展開できない時間があり押したのに反応せず被弾するのは非常にストレスが溜まる。ハイスピードメカアクションなのにハイスピードに操作すると反応しないのは何の冗談だ。これができないとなると回避を諦めその場で盾で受けるかラグや爆風で引っ掛けられるリスクを負ってQBするかになり攻撃の濃密な近距離の戦闘速度では近接攻撃以外に使用できない(この距離で足を止めて連射を受けられるほど盾の性能は良くない)。戦闘中は重ショのトリガーを引いて構えて発射するまでの時間さえ果てしなく長く待ちきれず発射する前にブーストしてしまう。そんなに長く待ってたら攻撃食らうわ馬鹿が!何度も繰り返すがACVIはあまりに遅すぎる(ACVの四脚スナキャが構える前から発射するまでの時間でさえACVIの重ショやランセツの発射より倍早い。それほど早いのでこの早撃ちは実戦技術だった)。ACVの反応速度の速さが恋しい。記憶する限りACVにこのような操作を妨げる硬直はなかったし機体が操作についてこれないこともなかった。少なくともACVで機体の反応が遅くて苛ついたことはない(思い返してみると壁蹴りには使用間隔の制限がなく0.2秒で連続使用する壁蹴りは自分の操作速度と操作精度を如実に反映し実に爽快だった)。ACVは自分の反応速度で戦えていたがACVIは自分の反応速度に追いついていない。何につけても不出来で劣化しており苛つかされる。もうやめようこんな遅すぎるゲーム。

ACVIの遅さは人間の反応速度の2−8倍、操作速度の4−16倍

ACVIには互いに干渉する操作に長い予備動作や硬直がありおおよそ武器攻撃(0.4, 0.0)、QB(0.0, 0.4)、キック(0.8, 0.8)秒となる。このためQBから武器発射までだけで0.8秒、キックからは1.2秒もかかり基本的にこの繰り返しとなる。最も強力かつ一般的な重ショキックコンボでも重ショの構え0.4秒のために0.4秒の先行入力または入力をキャンセルしないための待ち時間が必要になり発射後はQBまたはキックが続きコンボのループなどの次の操作が可能になるまで0.4秒または1.6秒かかるため合わせて0.8−2.0秒かかる。盾はこの間に挟まるにすぎず他のコンボで連続武器攻撃する場合も早く弱ければキックに競り負け遅く強ければ時間がかかる。従ってACVIの攻撃はコンボでさえ基本的に腕+肩またはキックの2回攻撃で2秒以上かかり平均してたった1秒に1回以下しか攻撃できず攻撃のたびに平均1秒以上待たなければならない。流れを振り返ると攻撃の0.4秒前に先行入力(寝ぼけてんのかてめえ)し攻撃完了を待ってからキックを入力(先行入力できないので実際にはここで0.2秒追加される)し操作可能になるまで1.6秒待つ。追撃したならさらに攻撃の完了0.4秒かキックの完了1.6秒を待つ。しかもACVIではキック連発が強行動である。これが苦行でなくて何なのか。周知のように人間の反応速度は0.2秒であり複数の指での連続操作は0.1秒間隔でできる。にもかかわらずACVIの操作間隔は最も主要なコンボでさえ0.4−1.6秒であり実に人間の反応速度の2−8倍、操作速度の4−16倍の遅さである。これは明らかにストレスが生じる異常な遅さである。ACVIは一般的な人間には到底快適に操作できない遅さで作られている

操作 予備動作(sec) 硬直(sec)
武器 0.4 0.0
QB 0.0 0.4
キック 0.8 0.8

耐性

ACVIでは耐性をスキャンできなくなっており低い耐性を突くことなど考えず硬直ハメするだけで簡単にすぐ勝てる安易なゲームになった事実を如実に表している。ACVIの戦闘面白いと言って動画上げてるやつはどいつもこいつも硬直ハメで喜んでるやつばかり。低俗で寿命の短い喜びと面白さである。硬直ハメ以外の上手い倒し方見つけてもでも硬直ハメのほうが速いじゃんで終わるクソバランスで萎える。上手い遊び方が一つしかない。これが遊び方の幅が狭いということである。

弾速

弾速返せよ

減衰

跳弾で減衰してるか確認しようにもダメージの視認が困難だし音の差も小さく着弾音が同期しておらず着弾音数が着弾数の半分以下(共通SEをBGM的に垂れ流してるだけじゃね)なので相乗的にわかりづらくACVのように音で直感的に跳弾による大減衰を把握できなくなった。減衰率もACVのように減衰曲線でなく減衰ありなしの2値で1歩下がるだけで1/10以下のダメージになり信じられなくらい雑で稚拙なものになっている(近接コンボ使わせるから減衰なんて気にしなくていいもんな)。他にもたかが数百メートルの射程を超えただけで空中で消滅するグレネードをどう受け止めればいいのだろうか(情けなくて目を覆わんばかりである。砲身の長さが拳銃とライフルくらい著しく異なるハンドグレネードとグレネードの射程が同じなのは素人目にもおかしいと思う人間はいなかったのか)。前作の開発者がいなくなるってこういうことなんだな。FCSといいAIといい全般的に技術の蓄積がリセットされ物理法則の再現もなくなりそれっぽい見た目だけの戦闘に退化というか初期化された。見た目は立派だが中身は素人の仕事だ。プロの仕事ではない。ACVIは過去作で受けたネタを寄せ集めた下手な二次創作のように見える。発売前から集大成、総集編、総決算的なタイトルだと期待していたが中身のない上辺だけの総集編だった。10年の空白で失った人材と技術をソウルライクで誤魔化すのも1度はやむを得ない。だが歴代最高であろう売れ行きで次も見た目だけ取り繕い内実素人同然の技術水準に甘んじる上辺だけのゲームを売り続けるなら見限る他ない。

パーツ数

なんかパーツ少なくない?脚とか中二以外各2つくらいしかないんだけど。四脚とタンクなんて軽重各1つ(+フロートみたいなの)で選択の余地まったくないじゃん。軽重の違いがわからない人が作ったのかVI的にいらない脚なのか。軽重まで分けてテンプレ級が最低各2つの選択肢が欲しいし見た目的に各4つ以上ないと選んでる感覚を得られない(四脚タンクは軽重各2つ合わせて4つくらいできるだろ)。

いまだにネットワークがおかしい

部屋に入ろうとしても一覧にでてきた10以上の部屋上から下まですべて参加に失敗することがある。まだ発売後2日目で数回しかやってないしブロックとかそういうレベルではない。ネットワークに再接続すると直った。ACVでマッチングしなかったのもこういうバグでは?

PV

PVの派手なボスが前半に固まってて後半地味なの多いし途中で予算なくなった映画みたいで見栄え悪い(中盤で予算切れたからデスワーム地味なの?)。分散させるくらい何も難しくないし固める意味何もないだろ。後半いよいよここまで来たようやく出会えたという楽しみがないじゃん。ラスボス1つ手前のかっこいいボスの顔見せとかやろうよ。

ラスボスがチンピラ

ラスボスがチンピラだと格がなくどうやっても萎える。ああいう小物は前座の噛ませ犬として前哨戦の捨て駒程度にしかしてはならない。大物に小物成分足したら足す前より小物になるに決まってるだろ。ラスボスと小物を混ぜるな。ところで真エンド、天の光が全てCになってるのにこれから始まるみたいなこと言われてもすでに終わってる(終末お迎え済み)ようにしか見えないんだが。これからが本当の地獄だってこと?コズミックホラー的なエンドなのもACとしてはピンとこない。人間にせよAIにせよ人間に理解できる人間的意思のある身近な存在による感覚的に理解できるこれまでの現実感ある危機を示した最後と比べて星の世紀みたいに漠然としていて現実味がなくなんかヤバそうだけどどうヤバイのかよくわからないモヤっとした曖昧な最後は輪郭のはっきりした解像度の高いビジュアルと設定のACにはミスマッチと言う他ない。ここもソウルライクの悪いところが出ている。ACVIは何かにつけてアーマードコアとソウルライクの相性の悪さを確認しただけのタイトルだった。ACに相応しいのは戦場で感じるような肌のひりつくようなリアルな危機である。ACに悪夢のようなファジーでファンタジーな恐怖感はいらない。現実で命がけで戦い続けた末に最後の最後で夢の世界に旅立たれても文字通り場違いすぎる。傭兵が求めるのは金や命のようなリアルな報酬である(時折の慰めと最後の愛も定番だがACにハリウッド映画みたいな湿っぽいシナリオは求めてない)。ゆえにACは少なくとも4以降はすべて実在的危機に対する生存という報酬が傭兵稼業と一貫性のある報酬となっていたがACVIの危機は最後だけ空想的で整合性がなく現実で足掻く傭兵の生き様を否定している。傭兵の生き様を否定している真エンドは当然ACと傭兵へのリスペクトがない。

コーラルが害悪物質すぎて焼く以外のルートが苦痛

あんな全自動星系反復自爆物質危険すぎて宇宙から消滅させる以外ないやろ。勝手に指数関数的に増殖して爆発して拡散増殖する核物質のようなもの。核物質×バイバイン=コーラル。1周目焼却以外考えられんかったし仲間殺してまで何の合理性もない他のルート選ぶのが苦痛。3周目破滅以外何の展望があるかわからん。残りの人類は衰退必至のコーラル汚染された宇宙でコーラルとの生存競争に負ける終末しか見えない(しばらく勝ちを譲られても将来的にコーラルが再び生存を脅かされたとき生存本能から人類を無力化しないとは考えられず人類が生存だけならできてもコーラルを滅ぼせるほど文明を発展させるのは極めて困難だろうことからいずれボーグよろしくコーラルに同化されるか絶滅するだろう)。またすべての星がコーラル汚染されたような描写だがこの光景を見るには宇宙の膨張を考慮せずほぼすべての恒星と銀河にコーラルが光速で到達するとしても約400億年、その光景が戻ってくるのに400億年で計約800億年経過していなければならずこれほどコーラルが充満して時が経っているなら共生の答えなどとうに出ているだろう。しかし私達がどこにでもいるという説明も光速を超えて情報伝達できない以上宇宙全体で一個の人格として同期を保つのは不可能であり分散すれば同期可能な範囲ごとの分化が不可避である。ワームホールで繋ぐとしても宇宙全体を同期させるには恐ろしい密度で必要になる。事前に超光速技術の提示があればSF的な説明もついたがその程度のものすらなく子供でもわかるほど画面いっぱいに科学的に破綻した最終エンドというのは見るに堪えない。

なぜこれほど高難易度のゲームに変わったか

一瞬で消費されず長く売ろうと思うと基本的にゲームの寿命を伸ばすための創作性か対戦機能が必要となる。だがACは機体構成くらいしか創作性を発揮できずフロムに良好な対戦機能を作りバランス調整を行う能力はないようだ。こうなると残る方法はクリアまでの時間を伸ばすしかない。現在一般的なのは継続的アップデートとキャラ等資源入手困難化による攻略速度調整によりそもそもクリアさせない方法だがACのように売り切りになると同じく資源入手困難化かまたは高難易度化により個々のプレイヤーの攻略速度を低下させるしかなくACは攻略速度を低下させゲームの寿命を伸ばすために高難易度化したと思われる。すぐにクリアされたら売れないじゃないですか(逆に中古市場に売られるし)。先鋭化必至の我慢比べのようなもののはずだがクリアできなくても話を合わせるために話題作を買う人が大量にいる時代になったのだろうか。いずれにせよ炎上と同じく次の世代は知らないので知らずに買う人は尽きないのが厄介なところだ。

バルテウスがバ◯ェラのパクry

さらに元ネタあるんかね(最高記録悪夢6連勝)

キャッシュアルゴリズムの評価項目

キャッシュアルゴリズムを選定する際の基本的な評価項目。これらを広く満たすほど汎用性が高くなる。

ヒット率(ワークロード)

用途を特定できないがLRUよりヒット率の高いキャッシュアルゴリズムを求める場合LRUより有意にヒット率の低い代表的ワークロードのあるキャッシュアルゴリズムは基本的に避けるべきである。特定の用途で使う場合ヒット率は目的のワークロードに近いベンチマークを参考にしなければならない。DS1はERPアプリケーションによる(おそらく反復的)データベースディスクアクセス、S3はウェブ検索エンジンによるデータベースディスクアクセス、OLTPはトランザクションにより歪んだデータベースディスクアクセス、GLIはループアクセスである。ベンチマークの多くはブロック単位のディスクI/OであるためKVSによるキャッシュサーバーの参考にはしにくいがウェブ検索エンジンのアクセスであるS3とコンテンツの統計的頻度を表すZipfはある程度参考になるだろう。なおキーと値が64bit数値または平均8文字の英数字であればDWCはLRUの95%、ARCの176%、LIRSの402%、W-TinyLFUの211%のキャッシュサイズを同じメモリサイズで使用できることからDWCのメモリあたりのヒット数はW-TinyLFUと同等か大きく超える。

耐性(レジスタンス)

ベンチマーク上のヒット率が高くとも実際には耐性の欠如によりヒット率が大幅に低下する可能性がある。基本的にはScan耐性とLoop耐性があればよくこの耐性がない主要キャッシュアルゴリズムはLRU、SLRU、ARCである。基本的耐性があっても固有の脆弱性を抱えるものもあり特定の集中的アクセスによりLIRSは履歴が肥大化、TinyLFUはヒット率が低下する。基本的耐性を完備し脆弱性のないものはDWCとW-TinyLFUだけである。

空間計算量(メタデータ)

キャッシュアルゴリズムには履歴などキャッシュサイズに比例して増加するメタデータを保持するものが多いことに注意しなければならない。除去されたエントリのキーを保持して履歴とするキャッシュアルゴリズムGC付き言語では履歴保持に使用するLinked ListをGCが管理するコストにより履歴サイズに比例して低速化する。またマップも履歴を保持しなければならないため肥大化し低速化する。キーまたはキーの参照先のサイズが大きい場合履歴がこれを保持しメモリを解放できないためメモリを大きく圧迫する。履歴のキーサイズは本体と合わせて2倍のものが一般的だがLIRSは最大2500倍にもなり当然メモリ不足でクラッシュする。厳密には履歴サイズを減らせばそのぶんキャッシュサイズを増やしてヒット率とヒット数を上げることができメモリ効率が上がるため履歴サイズの異なるアルゴリズムを同じキャッシュサイズとヒット率で比較することはできずメモリあたりのヒット数で比較しなければならない。

時間計算量(レイテンシ)

キャッシュアルゴリズムには一括処理により長時間停止しレイテンシスパイクが生じるものがあることに注意しなければならない。(W-)TinyLFUはキャッシュサイズの10倍のブルームフィルタ4個を一定間隔ごとに反復処理により一括リセットするため反復1回10nsとしてもキャッシュサイズ10,000,000(エントリ)でリセットに1秒から8秒を要する計算になる。LIRSも履歴を適宜一括削除する処理があり最大2500倍の履歴に対して無制限の一括削除が実行される。メモリのランダムアクセスレイテンシが約100nsであるため履歴の一括削除はLinked Listで保持されるものだけでも10,000,000エントリで1秒を要し辞書の削除と合わせるとさらに悪化する。

レイテンシ(スループット)

キャッシュは原則としてキャッシュヒットのレイテンシがキャッシュミスのレイテンシ以下でなければならない(このレイテンシは本質的にはスループットであるがキャッシュの速度は理論的にはアクセス単位で測定されるため一定時間内のスループットでなくアクセスのレイテンシとして説明される)。これはインメモリKVSやメモ化で顕著な問題であり履歴など線形に増加するメタデータを保持するキャッシュアルゴリズムメタデータを保持しないLRUなどの単純なキャッシュアルゴリズムより2倍以上低速となり高速化可能な対象が大幅に減る結果になりやすい。どれだけヒット率が高くともキャッシュしたほうが遅くなるならそのキャッシュアルゴリズムは役に立たないし使われないのである。(W-)TinyLFUはブルームフィルタをインクリメンタルリセットする場合でも1アクセスごとに配列要素を40個(10x4)から80個(20x4)もリセットしなければならずこのオーバーヘッドによるレイテンシ増大は同期処理において許容できないほど大きい場合も多いだろう。キャッシュミスがほとんどない場合はClock系アルゴリズムのほうが並べ替えを行わないぶん高速に動作する。特にレイテンシが重要な場合サンプリングによりヒット率を低下させてでも高速化される。

言語差(実装可能性)

キャッシュアルゴリズムには実装可能性(現実的に意味のあるものが実装可能か)が言語に依存するものがある。(W-)TinyLFUはキーをブルームフィルタに変換できなければならないためこの変換コストが高いJavaScriptなどでは低レイテンシな実装が困難となり用途が制限される。またLinked ListはGCの管理により非常に低速となるためARCやLIRSなど履歴保持にLinked Listを使用するキャッシュアルゴリズムGCなしで実装できる言語かによってレイテンシと適用範囲からのLRUに対する優位性、ひいては有用性が大きく異なる。さらにLinked Listで実装されるLRU自体も同様に低速となるため配列で実装されたClockのほうがLRUより高速となる可能性がありビット演算により高速化されたClockはLRUより高速となる可能性が高い。LRUはJavaScriptにおいて主要というか事実上唯一のキャッシュアルゴリズムだがほとんどの場合より高速なClockに対して何ら優位性がなくGC管理下の遅いLRUを無意味に使い続けているだけである。

比較

主要キャッシュアルゴリズムの具体的比較は以下を参照。

github.com

github.com

falsandtru.hatenablog.com

PjaxとSPAの違い

PjaxとSPAが全く同じ技術構成なのを知らずにPjaxを過去の技術だと思ってる知ったかぶりが多いので最も高度で完成度の高いPjaxライブラリであるpjax-apiの作者の自分が説明しておこう。

SPAとはPjaxをバンドルしたフレームワーク

Pjaxとはその語源からしてpushState+Ajaxである。そしてSPAの技術構成はフレームワーク+pushState+Ajaxである。すなわちSPAとは本質的にPjaxをバンドルしたフレームワークに過ぎない(Pjaxと対比されるSPAはツールセットとしてのSPAでありこれはアプリケーションフレームワークとしてしか存在し得ない。Reactはライブラリを自称しているがAngularやVueがフレームワークを自認していることからも明らかなようにSPAとして使用する場合はルーターなどと組み合わせフレームワーク化しなければならないものでありこれが主たる使用方法であるため悪質な詭弁に過ぎない。字義通りのSPAはSPAフレームワークで作ろうとPjaxで作ろうと何で作ろうとSingle Page ApplicationであればSPAである)。SPAを使っている限りPjaxも使っているのでありPjaxが過去の技術のごとき言説は無知を晒しているだけである。なおウェブ標準的にはAjaxはfetchに置き換えられているがPjaxも内部のAjaxをfetchに置き換えるのに何の支障もないので名前が古いままになるだけである。

実質的差異はデータフォーマットだけ

PjaxはAjaxなどの非同期通信APIによりHTMLを取得しページを更新するがSPAはJSONを取得しページを更新する。PjaxとSPAの共通部分の実質的差異は取得するデータのフォーマットがHTMLかJSONかという非同期通信の運用上の差異しかないのである。そしてその差異もそれぞれの利用方法において効率的なデータフォーマットを選んだ結果でありPjaxはページ遷移時にHTMLを差し替えるのみで足りるのでHTMLを取得しSPAはJavaScript上でDOMを常時状態管理してるのでJavaScript上の状態更新に適したJSONを取得しているに過ぎない。

HTMLとJSONで何が変わるか

データフォーマットをHTMLからJSONに変える主な利益はデータサイズである。HTMLよりもJSONのほうが簡潔で小さい。しかしPjaxでもそのような実装はやろうと思えば当然可能であり設計方針の違いでしかない。それよりもSPAがサーバーサイドの技術選択を制限する不利益のほうが大きい。

クライアントサイドにおいてはJSONを使用するSPAのほうが効率的に見えるがPjaxにおいてもダミーのXHRオブジェクトをJSONで取得した差分データで更新することで完全に同じ動作と効率を実現できpjax-apiはこの方式をサポートしている。

import Pjax, { FakeXMLHttpRequest } from 'pjax-api';

new Pjax({
  fetch: {
    rewrite: url =>
      FakeXMLHttpRequest.create(
        url,
        fetch(url, { headers: { 'Content-Type': 'application/json' } })
          .then(res => res.json())
          .then(data =>
            new DOMParser().parseFromString(
              `<title>${data.title}</title><body>${data.body}</body>`,
              'text/html'))),
  },
});

これによりSPAのすべての技術的優位性が完全に失われ、SPAは単に貧弱な独自構文とフレームワークを密結合したPjaxでしかなくなった。フレームワーク化だけなら意義があるがゴミみたいな独自構文など簡素な初期プロダクトは簡単に作れても後は死ぬまで10倍苦労するリボ払いのようなものである。

サーバーサイドにおいてもSPAは専用のフレームワークやライブラリのサーバー上での使用を要求しこれはほとんどの場合JavaScriptであるためJavaScriptという低速な言語によりサービスのスループットもレイテンシも非常に悪い不経済なものとなる。GoやRustなど他の高速な言語との組み合わせは不可能ではないが一般的とは言い難く自力で解決しなければならない部分が多いだろう。対してPjaxはブラウザ上で完結したライブラリであるためサーバーサイドの制約がなく任意の高速な言語と技術構成でサーバーを構築できる。またPjaxであればPjaxなし、Pjax(HTML)、Pjax(JSON)を容易(サーバーにJSON APIを追加するだけ)に混在させPjaxの設定のみでページ単位で変更できるがSPAでは多大なコストを要するSPA用サーバー(アプリケーション)の開発と運用を要するためPjaxのような段階的導入と一部変更は不可能か極めて非効率である(PjaxはJSON APIの追加以外既存サーバーを変更しないため設定を切り替えても単にもとのHTMLと行き来するだけだがSPAは既存HTMLサーバーをJavaScriptで作り直した高コストかつ低速な二重苦のSPA用サーバーで置き換えるためSPA用サーバーのSPA無効化は増加したコストが無駄になりドブに捨てることを意味する)。

SPA on frameworks*1 SPA on Pjax
Type Framework Library
Abstraction level High Low
Original template language Yes No
Intermediate layer Yes No
Data format JSON JSON or anything*2
UX integrity*3 Low High
Technical property Exclusive Coexistence
Ecosystem Dedicated Common
Old servers Dispose Keep
New servers Required Optional
Work on servers Redevelop all Add JSON APIs*4
Work on clients Redevelop all Reconstruct scripts*5
Partial introduction Coarse Fine
Location Servers and Clients Clients
Server constraints Strong Nothing
Dependence High Low
Learning costs High Low
Development costs High Low
Operation costs High Low
Running costs High Low
Removal costs High Low
Renewal costs High Low

*1 Such as React.
*2 You can send any efficient format instead of JSON and parse it on clients.
*3 Between MPA(standard web sites) and SPA.
*4 Just do it.
*5 To manage the lifetime of existing scripts. Since such management doesn't depend on SPA, these scripts are sharable and reusable with MPA and other SPA libraries.

github.com

さらに従前レスポンスを単一のHTMLにまとめてサーバーから送っていたところにJSONの各フィールドに分解して送りクライアントでHTMLまたはDOMに組み立て直す工程を追加するのはSPAかPjaxかにかかわらず非常に無駄が多く基本的に自己満足のためにクライアントのスクリプトへの依存を追加しメンテナンスコストを著しく上げるだけの結果に終わるためヘッダを見て差分HTMLを返すほうが一般的に全体として遥かに効率的でありまずそこから始めるべきである。JSONによる更新に適しているのはタイムラインやメールのようなデータだがこれはページと独立してAjaxで非同期に読み込み更新するほうが適しており実際これが一般的かつ主流な方法であるためこれらをページの一部としてSPAによりすべてJSON化してまとめて更新するのは無駄でありそうする必要性もない(リクエスト数が増加するが現在の開発ではほとんど考慮されない。逆に言えばリクエスト数を気にするほど軽量なページならデータを分離すべきではない)。ページ更新はHTMLとPjax、データ更新はJSONAjaxに分離するのが賢明である。ただし現在のユーザーはデータの遅延読み込みに慣れているものの検索結果の表示は伝統的に遅延しないのが通常であるため検索結果は同時に読み込むべきである(上記コードの変更によりHTMLページとJSONデータの並列読み込み同時更新も可能でありすなわちあらゆるデータ構成が可能)。理想的にはログイン状態では常に共通HTMLとユーザー別JSONに分離するのが最もネットワークおよびデータベース効率がよいがこれを実現できている大手サービスは見当たらない(データとスクリプトのサイズが大きくリクエスト数も多い大規模サービスでHTMLをキャッシュ可能にしても寄与が小さく開発の柔軟性が下がる不利益のほうが大きいのだろう)。

SPAとPjaxの開発上の違いはフレームワークとライブラリの違いであり既成品の組み立てキットを組み立てるか自分で図面を引いて部品を作って組み立てるかの違いである。設計能力も実装能力も兼ね備えた優れた開発者にとってフレームワークは耐え難く不自由でライブラリでなければ思い通りのものを作れない。設計能力の欠けた者、セミオーダーの既成品を量産するような仕事をしている者、とにかく早くプロトタイプを作らなければならない者にはフレームワークが適しているが最高の一点物を作るにはライブラリである。さらに必要ならフレームワークもライブラリも自分で作るのが最高峰の世界である。そしてReactもAngularも自社使用のために作られたフレームワークである。アプリケーションフレームワークというものは思い通りのアプリケーションを作ろうとするとどうしても細部に手が届かずフレームワークごと作り込まなければならなくなり、それができない外部の利用者は不便と妥協を強いられるものなのである。対してライブラリであれば不足分は基本的に独自アプリケーションの一部として生じるためライブラリに手を加える必要はない。一般的にアプリケーションはフレームワークではフレームの中に作られるのでフレームが妨げになると拡張困難になるがライブラリではライブラリの外に作られるので拡張を妨げずライブラリが適さなければ代わりの最小独自実装を内部的に作ればいいだけである。また陳腐化した場合の刷新もライブラリは段階的に行えるがフレームワークは一括して行うしかない。フレームに合わせて作る以外自由がないのがフレームワークである。

将来のPjax

Pjaxを構成するpushStateなどのHistory APIに代わるNavigation APIが現在策定中でありこれが標準化されればPjaxは名称と実装が完全に異なるものとなってしまうがライブラリとしては依然として内部実装を更新するだけで済むことである。機能的にもNavigation APIは基本的に既存APIを使いやすく再構成した便利API集で、現在のSPAとPjaxがすでに特に不足のないサービスを実現しているように基本機能は既存APIで足りている。従来不可能だったことが可能になる部分もあるものの現在特に不便を感じないように実際上ほとんど必要にならないものである。具体的にはリンクなどによるページ遷移の完全な捕捉と、厳密な遷移状態と遷移履歴の提供であるがオーバーエンジニアリングとユーザー行動追跡が促進されるだけである。そんなことより既存の標準APIを正しく実装しろと言いたい。History APIの一部でありPjaxに必要なscrollRestoration APIは標準化から7年に渡ってChromeFirefoxで真逆の動作になっていた。単機能のHistory APIですら長年互換性が盛大に壊れていたのに遥かに複雑な統合的APIであるNavigation APIのプロダクションレベルのブラウザ互換が確保されるまで何年かかるかわからない。ちなみに他のPjaxライブラリを使うのはやめとけどれだけ有名でも平行性制御できてないクソ実装だ。

ACVDはなぜ失敗したのか - マップとリスポンと没入感

ACVで毎日何度も一時間以上待ッチングしてた自分だがACVDは大幅に短い時間でマッチングできるようになったにもかかわらずわずか数ヶ月でやめた。何が悪かったのか?

マップがミスマッチング

ACVではほとんどのマップが比較的狭く遮蔽物の多い要所で至近距離から一気に乱戦に持ち込み決戦できるようにデザインされていたのに対しACVDは遮蔽物に乏しい開所を被弾しながら突破しなければならないマップが多い。これは数十人でリスポンしながら戦うFPSのマップデザインである。おそらくACVDのマップデザイナーはFPSのマップデザインをそのまま輸入したのだろう。もちろんこれは4vs4リスポンなしのACVDにマッチしない。このような多数の犠牲を出しながら物量で突破する上陸戦や要地攻略のような戦闘はFPSのように多人数でリスポンしながら戦わなければ成立しない。にもかかわらずACVDでは侵攻側は明らかに集中砲火を受けるだだっ広い開所に突撃することを強いられ防衛側は豊富な遮蔽物に隠れながら集中砲火を浴びせることができる。このような地理的優劣はACVにもあったがACVDの地理的優劣の格差はACVの何倍も大きく著しく不利な戦闘をリスポンなしで強いられるうえ侵攻序盤の開所のマップのほうが終盤の閉所のマップより接近困難で不利なマップになっており難易度が序盤が難しく終盤が易しい、序盤と終盤で逆転したものになっている。さらにACVDの開所のマップは開所であるゆえACVと違い侵攻ルートからの逸脱を制限し正しい侵攻ルートに誘導することが困難であり初心者ほど容易に無意味に分散し各個撃破される誘引が序盤ほど強い。これほど初心者に不利なゲームデザインではユーザーが離脱して当然である。ヘビーユーザーでトップチーム所属でランクマ上位の自分ですら離脱したのだ。アーマードコアは大型機械に乗って広い空間を機動するゲームであるが個の力がいかに強大であろうとわずか4vs4で万単位の兵力をぶつけ合う軍事作戦を再現することは不可能であり4vs4の集団戦は本質的にはむしろ少数精鋭の特殊部隊の襲撃作戦に近い。したがってアーマードコアの対人戦はどれだけ軍事的要点を押さえた戦場を再現しようとその戦闘は特殊部隊の市街戦や屋内戦のように豊富な遮蔽物を利用して接近し近距離で決戦を行うものでなければならないのである。

リスポンの不在

マップと戦闘を適切にデザインしても死亡後リスポンできず戦闘終了まで無力感を味わい続けることを強制されるのはやはり優れたゲームデザインとは言えない。何かしらの十分な希望を持って戦闘の経過を見られるようにすべきだろう。生き残ったプレイヤーとしてもチェスの終盤戦のように貧弱な戦力で長期戦になるのは退屈であり将棋のように最後まで劇的な戦いができたほうが面白いのは明らかである。したがってやはりゲームとしてリスポンは提供するべきである。しかしリアル寄りのゲームで4vs4でゾンビのように復活して戦ってもリアリティが損なわれ面白くない。そこでストック制を提案したい。出撃部隊は最大出撃数、ACVDなら4機から残存機体数を引いた数を上限として倒した敵の数だけリスポンをストックしリスポンできる。つまり4機生存してるなら1機もストックできず3機生存なら1ストック可能、1機生存なら3機ストック可能、全滅してもストックがあればリスポン可能となる。実際の出撃数でなく最大出撃数を基準とすることで少人数で出撃または回線落ちした側に戦力差を補う優位性を与えることができる。

没入感がない

ACVと比べてACVDはなんか後方視点から見える自機が小さく見えて没入感がなかった。これがACVDを短期間でやめた一番大きな理由かもしれない。ベースサイズよりブースト時の最小サイズ?マップが広すぎたり敵との平均距離が遠いせいで最小サイズの時間が長いからかも。視界は広いほうが戦闘に有利だが戦い続けることが第一なので調整できるようにしてもらいたい。

falsandtru.hatenablog.com

キャッシュアルゴリズムの比較

アプリケーションなどOSより上に作られる高水準のプログラムではハードウェアの速度と容量を考慮しない数学的キャッシュアルゴリズムが使われ主にこれを本稿の対象とする。キー探索用マップと明示的キャッシュサイズ(対となる値が保持されているキーのサイズ)は計算量に含まれない。

LRU

最も単純かつ高性能な基礎的キャッシュアルゴリズム。そのため性能比較のベースラインとして常に使用される。逆に言えば実用最低水準の性能である。スキャン耐性皆無でスキャン一発でキャッシュとヒット率がリセットされゼロからやり直しになるため非常に脆く不確実な性能となりベンチマークにおける性能が表面上さほど悪くなく見えても実際の性能はこのような外乱により大きく低下しやすい。このためLRUより高度な主要アルゴリズムはすべて大なり小なりスキャン耐性を備えている。ちなみにプログラミング言語最大のパッケージマネージャであるJavaScript(NPM)はパッケージ数100万以上を誇るにもかかわらずLRUしかまともなキャッシュの実装がなくnodeやTinyLFUのような人気のフレーズを付けた名前に名前と無関係の実装を貼り付けたクリックバイトの詐欺パッケージとすぐエラーを吐く壊れたガラクタばかり豊富なスラムみたいな状態となっている。後発のRust(10万パッケージ未満)とGoは理論的に優れた実装がガンガン追加されてるのに全体的に理論的に優れた実装に乏しくキャッシュも最も初歩的で原始的なLRUしか使えない超低空飛行プログラミングに疑問も不満も感じず理論的教養を持つ天上界のプログラマに仕事か気まぐれで運よく優れた実装を恵んでいただけるまで刃の潰れた斧を延々使い続け時間ができても流行りのスコップで飽きもせず同じ穴を何度も掘っては埋め続けるか偽ブランド作りに勤しむ、それがJSerクオリティー。注目を集めるために著名な名前を偽装して名前空間と検索結果を汚染する最低水準のプログラマが集まってろくに管理されてないのでとにかく質と治安が悪い。使う側も容量超えるとクラッシュするキャッシュもどきをキャッシュと思い込んで毎週200万DLして使ってるポアな世界。質は量から生まれるとは何だったのか。

Clock

主にOSがページングのために使用する、LRUの高速な近似アルゴリズム。エントリの追加がO(n)であるためアプリケーションなどで使用する一般的なキャッシュアルゴリズムとしてはLRUより低速と認識されその領域では使用されていないが広く蔓延した誤った認識である。リストを使用しないClockはGC管理下の低速なリストにより実装されたLRUよりも高速になりうるものでありさらにビット演算により最悪計算量O(n)を少なくとも32倍高速化できる。JavaScript(V8)における筆者の実装では最も人気かつ主要実装の中で最速のLRU実装であるIsaacsのLRU(ISCCache: lru-cache。LRUCache: 筆者によるより高速な、JavaScriptにおける最速のLRU実装。DW-Cache: Dual Window Cache)の等倍から2倍の速度を実現しており他の多くの言語でも同様にO(n)のClockのほうがO(1)のLRUより高速になる可能性がある。また近似というと低性能の印象があるが上記主要ベンチマークで比較するとClockのほうがLRUよりヒット率が1-2%前後高い場合が多く5-10%以上高い場合もありヒット率の観点からもLRUよりClockのほうが優れている。なぜ我々は長年LRUに甘んじていたのか。

github.com

'Clock    new x 982,257 ops/sec ±4.80% (102 runs sampled)'

'ISCCache new x 11,457 ops/sec ±1.49% (117 runs sampled)'

'LRUCache new x 21,184,221 ops/sec ±0.18% (123 runs sampled)'

'DW-Cache new x 5,459,649 ops/sec ±0.41% (123 runs sampled)'

'Clock    simulation 100 x 10,520,040 ops/sec ±2.24% (120 runs sampled)'

'ISCCache simulation 100 x 8,148,950 ops/sec ±1.87% (119 runs sampled)'

'LRUCache simulation 100 x 9,110,929 ops/sec ±2.52% (118 runs sampled)'

'DW-Cache simulation 100 x 6,778,262 ops/sec ±2.27% (120 runs sampled)'

'Clock    simulation 1,000 x 8,738,216 ops/sec ±2.20% (118 runs sampled)'

'ISCCache simulation 1,000 x 7,298,708 ops/sec ±1.85% (119 runs sampled)'

'LRUCache simulation 1,000 x 8,120,011 ops/sec ±2.55% (117 runs sampled)'

'DW-Cache simulation 1,000 x 6,656,796 ops/sec ±2.28% (119 runs sampled)'

'Clock    simulation 10,000 x 8,546,724 ops/sec ±2.24% (119 runs sampled)'

'ISCCache simulation 10,000 x 6,479,979 ops/sec ±1.81% (120 runs sampled)'

'LRUCache simulation 10,000 x 7,455,903 ops/sec ±2.42% (120 runs sampled)'

'DW-Cache simulation 10,000 x 6,469,169 ops/sec ±1.95% (121 runs sampled)'

'Clock    simulation 100,000 x 5,733,062 ops/sec ±1.61% (118 runs sampled)'

'ISCCache simulation 100,000 x 3,179,438 ops/sec ±1.84% (109 runs sampled)'

'LRUCache simulation 100,000 x 3,746,025 ops/sec ±2.09% (116 runs sampled)'

'DW-Cache simulation 100,000 x 3,319,309 ops/sec ±2.16% (114 runs sampled)'

'Clock    simulation 1,000,000 x 2,949,250 ops/sec ±3.75% (104 runs sampled)'

'ISCCache simulation 1,000,000 x 1,487,123 ops/sec ±3.06% (100 runs sampled)'

'LRUCache simulation 1,000,000 x 1,725,359 ops/sec ±4.29% (106 runs sampled)'

'DW-Cache simulation 1,000,000 x 1,740,517 ops/sec ±2.10% (110 runs sampled)'

SLRU (Segmented LRU)

LRUを固定比率で分割しキャッシュヒットの有無で格納先を変える。適切な比率であればLRUより高い性能が期待できるが適切な比率は用途と状況により異なり当然動的な変化には対応できず汎用のLRU、特化のSLRUの関係にある。しかし試用区間(基本20%)を超える再利用距離のデータは間に他のデータへのヒットが区間超過分ない限り絶対にヒットしないため対象のワークロードにおいて試用区間が不足しないか事前調査を要する。SLRUにはキャッシュが埋まるまでは規定の本来の試用区間を超えて最大で100%まで試用区間が延長されることで本来より捕捉可能な再利用距離が長く高いヒット率で開始されさらに保護区間へのヒットにより捕捉可能再利用距離が延長された状態で動作する暗黙の初回ボーナスがある。このため使用開始直後は初回ボーナスによりヒット率が高くともワークロードやトレンドが大きく変化すると保護区間へのヒットの減少すなわち捕捉可能再利用距離の減少により捕捉可能再利用距離が本来の試用区間に近づき徐々にまたは急激にヒット率が低下する可能性がある。つまり初回ボーナスによるブーストを失うと二度と取り戻せずワークロードの一部を切り取った一般的なベンチマークではヒット率が過大となる可能性があるため正確な比較と評価ができない。このように20%という試用区間の小ささによりワークロードによってはキャッシュが全く機能しなくなるまたはワークロードやトレンドの変化に追従できずヒット率が低下する可能性があるという理論的問題と信頼性の低さがSLRUが先進的キャッシュアルゴリズムの比較対象に含まれない理由であろう。高いヒット率を得られる状況でも逆に保護区間の不足によりヒット率が伸びず相対的に低下する可能性があり帯に長く襷に短い扱いにくさがある。

ARC (Adaptive Replacement Cache)

SLRUの比率をキャッシュサイズの(本体と合わせて)2倍の履歴とキャッシュヒットにより動的に変更することで動的な変化に対応する。高いヒット率から人気があったが特許により使用が制限されていることと4つのリストを操作するオーバーヘッドの高さから忌避されている。そのため多くのプロダクトがLRUに甘んじるかSLRUを劣化版ARCとして任意の固定比率で妥協して使うか粉飾欠陥クソアルゴリズムのLIRSを騙されて採用し当然クラッシュするもいまさら低性能な(S)LRUに戻すこともできず惰性で騙し騙し使うはめになった(プロプライエタリでは特許に抵触しないよう改変したARCを使う場合もあるようだ)。その後はすっぱい葡萄もあってかキャッシュアルゴリズムの性能はワークロードに依存しARCはそれほど優れたアルゴリズムではないとディスられ続けている(代わりの優れたアルゴリズムを提示できるわけでもないのに)。実際ARCはスキャン耐性が低くループ耐性もないため現在では時代遅れのアルゴリズムと言っても過言ではなく実装に使うビルトインAPIの制限によりLRUより履歴のぶん少ないサイズしか指定できない場合もある(JavaScriptのV8のMapは最大224エントリだがより少ない1000万でもLRUが落ちる場合が見られARCはわずか500万で落ちた)。なおARCの基本特許はすでに切れている*1がすでに上位互換のDWCがあるため用済みでありいまさら戻ってこいと言われてももう遅い!

DWC (Dual Window Cache)

時間空間ともに定数計算量でありながら高水準のヒット率と耐性を実現する最高性能の定数計算量キャッシュアルゴリズム。DWCよりヒット率の高い主要アルゴリズムはLIRSと(W-)TinyLFUしかないが後述するようにLIRSは性能を粉飾したために致命的欠陥が生じており(W-)TinyLFUも用途に制限があるためDWCがすべての主要汎用キャッシュアルゴリズムの中で最小の計算量でありながら最高の性能となる(マイナーな他のアルゴリズムは共通のベンチマーク結果を公開していないため比較不能、W-TinyLFUは動的ウインドウとインクリメンタルリセットを備えたものは最高性能の汎用アルゴリズムとなる可能性があるが現在該当する実装は公式実装であるCaffeine以外見当たらず、Caffeineにおいても両機構使用時のベンチマーク結果はなく、論文そのままの固定ウインドウと一括リセットの実装は汎用性が低いため無調整で全般的に高性能なDWCと同等以上の汎用性をCaffeineが実際に備えていることを実証する具体的資料はない。また1エントリあたり40byteのオーバーヘッドがあるためエントリが小さい場合W-TinyLFUのオーバーヘッドのぶんDWCのキャッシュサイズを増やしたほうが全体的な性能が高い可能性がある。1エントリのメモリ使用量がキー、値、オーバーヘッドそれぞれ1byteで計3byteとすると減らした履歴サイズの2/3のキャッシュサイズを増やせるといった具合であり履歴サイズが2倍ならキャッシュサイズを66%増やせる。キーと値が64bit数値または平均8文字の英数字であればDWCはLRUの95%、ARCの176%、LIRSの402%、W-TinyLFUの211%のキャッシュサイズを同じメモリサイズで使用できることからDWCのメモリあたりのヒット率はW-TinyLFUと同等か大きく超える)。通常のヒット率においてもLIRSとTinyLFUは一般的ワークロードにおいてLRUと同等か大幅に劣る場合があるがARCは最大性能が低いものの安定してLRUより性能が高くARC系のDWCも非常にキャッシュサイズが小さい場合を除き全般的にLRUより性能が高い。またLRUより高性能なアルゴリズムの多くがエントリ削除後もキーを保持し履歴として使用する線形空間計算量のアルゴリズムであり標準ライブラリなどの標準的なキャッシュAPIではLRU同様エントリ削除と同時にメモリ解放可能な定数空間計算量のアルゴリズムが第一に求められるだろう(LRUを一般的に置換・陳腐化可能なアルゴリズム、(S)LRUより大幅に高性能な定数計算量アルゴリズム、ループ耐性のある定数計算量アルゴリズム、たぶんすべてにおいて史上初)。ただし情報量(履歴)の不足を補うため全体的に統計精度への依存度が上がっており標本サイズが小さくなるほど情報量と統計精度の低下により性能低下しやすくなる。メインアルゴリズムの統計精度が1パーミルであるため推奨キャッシュサイズは1,000以上となる。LRUしかない地獄のJavaScript界で絶対にLRUなんて使いたくない作者により作られた。主に3つの新機構による複合構成となっている。名前はメインアルゴリズムにおいて概念上キャッシュ比率の計算に2つのSliding windowを使用することに由来するが実装上は1つのウインドウから両方の計算結果を算出するよう簡略化している。単にSliding Window Cacheとしたほうが簡潔だが多くの論文で異なるセマンティクスでSliding windowが用いられているため混乱を避けるためこの名前を避けている。上記グラフは主要ベンチマークにおける主要アルゴリズムの比較でありDWCが定数計算量でありながら先進的な線形計算量アルゴリズムと同等の性能を実現している画期的アルゴリズムであることを示している。このような定数計算量キャッシュアルゴリズムは他になくDWCが唯一である。

github.com

LIRS

キャッシュサイズの最大2500倍の履歴を保持するため採用プロダクトをメモリ不足でクラッシュさせてきた詐欺アルゴリズム。どこも他のアルゴリズムに変えるか履歴サイズをパラメータ化して責任転嫁して無理やり使っているため本当の性能は誰にもわからない。論文が著名で多数の有名プロダクトで採用実績があっても信頼できる優れたアルゴリズムである証明にはならないのである。履歴はLIR末尾またはHIRエントリにヒットするか最大値に達するまで拡大し続けヒットすると条件を満たすまで履歴をたどり一括削除するためレイテンシスパイクの原因ともなる。メインメモリのランダムアクセスレイテンシ約100nsを基準とするとLinked Listだけでも履歴含め10,000,000エントリの一括削除で1秒の停止とスパイクとなり辞書の削除を合わせるとさらに悪化する。またスループットもリストなどの非常に長い参照のGCには急速に所要時間が増える転換点がある場合があり数倍の履歴でもスループットが急速に低下するためそのようなGCを持つ言語ではメモ化などのキャッシュによる高速化が50%以下と低い場合履歴サイズが転換点を超えるとLRUやキャッシュなしのほうが速くなるリスクが高い(JavaScriptのV8ではDoubly Linked Listは1万から10万ノード、Mapは10万から100万エントリ付近からスループットがノード数10倍あたり約1/2から1/3に急速に低下するよう変化する)。キーの検索にマップを使っていれば当然マップも履歴のぶん肥大化および低速化し、LIRSの実用的な履歴サイズの推奨値は3−10倍である。クラッシュの実害とこれらの問題にもかかわらず使われ続けたのは当時ループ耐性のある高性能キャッシュアルゴリズムが他になくいまさら(S)LRUに戻せなかったからであろうが現在は他にもループ耐性を持つDWCとW-TinyLFUがありとっくに唯一の選択肢ではなくなっているためあえて危険で性能もわからないLIRSを使う必要はない。なお近年の研究ではキーの履歴サイズはキャッシュサイズの2倍が規範的標準となっている様子が伺え今後適切な履歴サイズが定まるまでせいぜい3倍が限度だろう。

TinyLFU

非常に高性能な新キャッシュアルゴリズムとして知られているが実際には本当に性能が高いのはW-TinyLFUだけでTinyLFUのヒット率は総合的にはLRUより悪いことが論文に明記されており、人気の高いRistrettoは特に論文通りのSLRUでなくLFUをメインキャッシュに使用しているためヒット率が大きく低下するワークロードが生じていることに注意しなければならない(OLTPではLRUより大幅に悪く、トレンドの変化が大きいワークロードではLFUの特性により同様に性能が低い可能性がある)。ブルームフィルタ(CountMinSketch)は削除操作不可能であるためキャッシュエントリを削除するほど偽陽性および偽陰性が増え一定期間内の任意または有効期限超過による削除数に比例して性能が低下する。またブルームフィルタがバーストアクセスで飽和し性能がSLRUの水準にまで低下する可能性があるため性能劣化の脆弱性を抱えているに近い状態であり適切にオートスケールできなければ攻撃や肝心な大量アクセスで想定以上の急速な性能劣化に耐えられない可能性がある。スキャン耐性皆無のLRUほどではないがW-TinyLFUの危険(不安全)な未完成品というのがTinyLFUの実態であり用途に対してトレードオフが許容可能か検討と検証なしに使うべきでないアルゴリズムである。さらに定期的にブルームフィルタの一括リセットのための非常に大きな反復処理が走りレイテンシスパイクが生じる。ブルームフィルタのサイズはキャッシュサイズ(最大エントリ数)の10倍であるためキャッシュサイズが10,000,000で100,000,000回(Ristrettoなど実装とサイズによっては最大でさらに2x4で8倍の800,000,000回、メモリ消費は1要素8bit(1byte)であるため400MB(100MBx4)から800MB(200MBx4))の反復処理となり、反復1回10nsでも1秒(8秒)の停止とスパイクが生じ、キャッシュサイズ、言語、実装により容易に悪化する。(W-)TinyLFUのレイテンシは許容限度を超えており少なくとも現在の実装ではオンラインサービスなどレイテンシが考慮される用途ではエンタープライズレベルではスケーラビリティが低すぎて使い物にならないだろう(にもかかわらずオンラインで使ってるところはおそらくキャッシュサイズがさほど大きくないかスパイクに気づいてないか放置している)。(W-)TinyLFUは近年人気の高いキャッシュアルゴリズムだがレイテンシに重大な欠陥が存在するにもかかわらずこれを認識せず盲目的に使われているように見える。なお(W-)TinyLFUはキーをブルームフィルタに変換する必要があるためキーのポインタのアドレスを取れないような変換コストが高い言語ではオーバーヘッドが高い(JavaScriptは非常にオーバーヘッドが高くなる言語の一つである)。またポインタのアドレスを使用する場合はアドレスの再利用により偽陽性が生じヒット率が低下する可能性がありどのような状況でどの程度低下するかは未知数である(同じアドレスが頻繁に再利用されれば当然著しく低下する)。ベンチマークに使用されているブロックアクセスにおいても書き込み範囲のアドレスにおいて同じ問題が生じるはずでありブルームフィルタから減算するとしないとにかかわらず精度が低下するが公式実装であるCaffeineにおいてもこの精度低下が生じない方法で測定(書き込み範囲はキャッシュに追加または無効化されなければならないはずだが単に処理が省略されている)されているため書き込みを含むワークロードの公表されているヒット率は誤った測定方法による不正確なものである疑いがある。

W-TinyLFU

最もヒット率の高いキャッシュアルゴリズムだが削除頻度が高いかレイテンシ要件がある場合は前述の問題のため採用できないだろう。よく見られるW-TinyLFUのヒット率はおそらく動的ウインドウのもの(まさか比率指定を隠したチェリーピッキングではなかろう)で固定ウインドウの実装を使うならば適切なウインドウ比率を自分で設定しなければならない。動的ウインドウのW-TinyLFUはキャッシュを頻繁に作り直さずレイテンシに寛容またはキャッシュサイズが小さくエントリを頻繁に削除せずその言語で効率的に実装できるのであれば優れた性能を期待できる。ただしCaffeineでは動的ウインドウとインクリメンタルリセットが実装されているものの両方を使用した場合のヒット率は明らかでなく動的ウインドウとインクリメンタルリセットを備えた実装が期待通り全般的に高性能であることを実証するデータはない。またインクリメンタルリセットする場合でも1アクセスごとに配列要素を40個(10x4)もリセットしなければならず本質的にオーバーヘッドが高いためレイテンシへの要求水準の高いインメモリKVSやメモ化などでの有用性は限定的とならざるを得ない。エントリサイズが小さければ前述のようにオーバーヘッドの比率が上がりヒット率で補えないほどキャッシュサイズごとヒット率が下がる。さらにOSや言語のメモリ割り当て方法によっては前述のようにメモリアドレスの頻繁な再利用によりヒット率が著しく低下する可能性があるため信頼性が低い。要するに性能低下要因が多くDWCのように何も考えず何にでも使えるアルゴリズムではなく取り回しが悪い。DWCは万能な軽量級でありW-TinyLFUは条件を満たせば最高性能を発揮する重量級である。なおW-TinyLFUは形式的にはエヴィクションアルゴリズムなしには機能しないアドミッションアルゴリズムだが動的ウインドウを備えたものは本質的にはARCやDWCと同様にウインドウキャッシュ(LRU)とメインキャッシュ(SLRU)の2つのキャッシュ比率を適応的に調整するエヴィクションアルゴリズムであると言える。

評価項目

falsandtru.hatenablog.com

*1:https://patents.google.com/patent/US7167953B2/en、もう一つ追加の特許https://patents.google.com/patent/US20070106846A1/enがあるがどう関係するかよくわからない