ValueOnlyバイナリフォーマット
Wienerが採用する独自バイナリフォーマット「ValueOnly」の技術解説です。
ValueOnlyとは
通常のバイナリやJSONはデータとともにキー名を格納します。
{ "item_id": 1001, "name": "Sword", "hp": 0, "attack": 45 }
WienerのValueOnlyフォーマットはキー名を持ちません。代わりに、コンバート時に生成されたC#/C++コードがフィールドのオフセットを記録しており、プロパティアクセス時にそのオフセットを直接参照します。
速度の仕組み
JSON / MessagePack:
データ受信 → パース → キー名照合 → 値取得
ValueOnly:
データ受信 → オフセット計算 → 値取得(キー照合ゼロ)
キー名の照合が一切発生しないため、データ量に関わらず一定時間でアクセスできます。これが200万セルでも一瞬のロードを実現した設計の核です。
セキュリティへの貢献
キー名がバイナリに存在しないため、バイナリエディタで開いてもフィールド名が露出しません。簡易難読化機能と組み合わせることでさらに強固になります。
生成されるコードとの関係
ValueOnlyはWienerが生成するコードとセットで機能します。
// Wienerが生成するコード(例)
public class ItemData : IWienerDictionaryData<int>
{
public int ItemId { get; private set; }
public string Name { get; private set; }
public int Attack { get; private set; }
public void Read(WienerDataReader reader)
{
ItemId = reader.ReadInt32();
Name = reader.ReadString();
Attack = reader.ReadInt32();
}
}
reader はバイナリを先頭から順に読み進め、読んだ分だけ内部オフセットを進めます。各 ReadXXX 呼び出しは「次のフィールドを読んで前に進む」だけなので、キー名の照合も余分なシーク処理も発生しません。
通常の LoadBasicPack は、コンバート時に生成されたソースコードと basic.bytes の構造が完全に一致していることを前提にロードします。これはリリース時に余計な判定を入れず、高速に読み込むための通常経路です。
一方で開発中は、YAMLや生成コードを更新した直後に古い basic.bytes を読み込むなど、ソースコードとバイナリの構造が一時的にずれることがあります。この場合は開発用ロードメソッドの LoadBasicPackFromHash を使うことで、完全一致していなくても、バイナリ内のハッシュと一致する変数だけにデータを読み込めます。バイナリに存在しない変数はdefault値になり、バイナリに存在してソースに存在しないデータは無視されます。
LoadBasicPackFromHash は差分開発や検証用の安全網であり、通常ロードより遅くなります。リリース用途では、ソースコードとバイナリを同じコンバート結果から生成し、LoadBasicPack で完全一致ロードする運用を推奨します。
注意事項
ValueOnlyはWiener以外のツールでは読み取れません。汎用性より速度・安全性を優先した設計判断です。
デバッグや他システムとのデータ共有には、用途に応じてテキスト形式の出力を活用してください。ExcelやGoogle Sheetsの生データに近い確認には CSV、YAMLで指定した項目だけを抜き出す用途には SQL(CSV)、汎用的なデータ連携には Json を使用できます。
関連
- C#フォーマット: LoadBasicPackFromHash — 開発用のハッシュ一致ロード
- 簡易難読化 — ValueOnlyと簡易難読化の組み合わせ
- CSV — ExcelやGoogle Sheetsの生データ出力
- SQL(CSV) — YAMLで指定した項目のみを抜き出した出力
- Json — 汎用的なJSON出力