爆速シリアライズSimple Binary EncodingをRustで導入


https://speice.io/2019/09/binary-format-shootout.html
このサイトによると、FlatbuffersやCap’n Protoよりも断然速いSBE(Simple Binary Encoding)というのがあるらしいので、動かしたくなった
しかし、あまりにも誰も使われなかったので、公式のRustサポートがなくなったらしい

もう少し評価されても良いコードだと思ったので、導入方法だけ書いておく
(日本で、少し流行らねえかな)

サンプルを動かす

普通にgithubからcloneして、
https://github.com/real-logic/simple-binary-encoding

git checkout 23e8c16caf03d2b073bc850f37b1fb68cecbe54a

公式のRustのサポート終了したバージョンまで戻します。
ターミナルで、rootディレクトリまで行って、

./gradlew
と入力します。
(Javaを誰でもビルドできるようにするツールらしい)

次に
./gradlew generateRustCodecs
と入力します。
これで、sbe-samples/src/resources/...のxmlが、rust/car_example/src/car_example_generated_codec.rsに変換されました。
このrsファイルを使えば、依存crateがなく純粋なRustのコードだけで、SBEにシリアライズ/デシリアライズが可能になります。

自分のスキーマを書く

build.gradleから、generateRustCodecsで実行される行動を変更できます
build.gradleのtaskに書いてあるdependsOnのアクションが実行されるようになってるみたいです

build.gradle
task generateRustTest(type: JavaExec) {
    main = 'uk.co.real_logic.sbe.SbeTool'
    classpath = project(':sbe-all').sourceSets.main.runtimeClasspath
    systemProperties(
        'sbe.output.dir': 'rust/my-proj',
        'sbe.xinclude.aware': 'true',
        'sbe.target.language': 'uk.co.real_logic.sbe.generation.rust.Rust',
        'sbe.target.namespace': 'my_codec')
    args = ['mine/my-entity.xml']
}

task generateRustCodecs {
    description = 'Generate rust test codecs'
    dependsOn 'generateRustTest' // 新しく追加
    // dependsOn 'generateRustCarExample', 'generateCarExampleDataFile' // 元々の実行関数
}

などとします。

スキーマは、
xmlの
sbe:messageSchemaの中に書きます
以下、
xi:includeで、他の読み込むxmlを書きます
typesでエイリアスタイプを定義します
sbe:messageにそのEntityの内部変数を定義します。

最後に

最近、SBEのRustのサポートは終了したのですが、現状、多言語間で通信可能な、最速に近いバイナリフォーマットっぽいので、いろいろ使い道はありそうです。Googleの、Flatbuffers, Protobufも悪くないのですが、SBEは完全に独立していて、高速に動くし、割といいのでは?と思ってます。

Rustの流行度次第では、またサポートもすぐに再開するかもなので、RustとSBEがもっと流行ればいいなと個人的に思ってます。

あと、serdeとかあるし、逆にRustのコードから、SBEのスキーマを書き出すのも普通にできそうですよね。(簡単そうならやってもいいかも)