組み込み向けのデータ伝達プロトコル

もう長いことソフトウェアエンジニアリングを仕事にしてきましたけれども、データの伝達をするプロトコルとは特になじみが深く、自前プロトコルを含め色々なものを使ってきました。こういうプロトコルを data serialization protocol 日本語に直訳するとデータ一本化プロトコルかな?といいますけど、業界で人気のあるものというと例えば Protocol Buffers、Apache Arrow、ちょっと古いところでは Thrift など、その実装と組になって数限りなくあります。こんな感じ

https://en.wikipedia.org/wiki/Comparison_of_data-serialization_formats

しかしどの方法もライブラリがでかいかプロトコルが非効率かどっちかです。組み込みで使うマイクロプロセッサで使うにはきついのではないの?こういったプロトコルのほとんどが組み込みで使う前提はなかったんだろうなあと思われます。例えば Protocol Buffers はメッセージサイズを小さくするためにエンコード・デコードを担当するやたらでかいライブラリを組み込まないといけないし、ヒープもじゃんじゃん使います。それより速くてメモリ利用効率がいいよといううたいの Flat Buffers では受信データはバッファに入れたままそこから直接値を取り出すのが売り。ちょっと待って、組み込みだとそんなに長くバッファを保持したくないんだけど。値を使ってる最中に次のメッセージがきたらどうするの?そもそもヒープなしでやれるよね?と心配ごとてんこ盛りです。あんまり使う気になれない。

これは組み込みをやる人の間で問題にならないのかな?皆さんどうしているのかな?と思ってネットをあさってみたら、まさに全く同じ話のサブレディットが見つかりました。

これは面白い議論でした。最後に出てきた 「Type-length-value プロトコルを自分で実装したら?結構簡単よ?」という話が一番納得いくし賛同者も多かったです。

このプロトコルは小ワザとして自分でもしょっちゅう使うものでしたけど名前が付いているとは知らなかった。

Type-length-value はどういうものかというと、データは名前と値の組み合わせ (フィールド) の集合として定義して、固定長の名前 (type)、値の長さ (length)、値 (value)の順でバイト列に収めて行くというものです。データ型は名前に紐づけして送信側受信側両方が知識として知っているという前提です。とらえようによっては普及している JSON フォーマットのバイナリ版という見方もできますね。このプロトコルの便利なところは、受信側が知らないフィールドを受け取っても読み取りだけはできるということです。受信側は無視するなりエラーとして処理するなりそこは設計次第ですが通信は破綻しません。なので必要に応じて後付けでフィールドを追加できます。

上記の既存ライブラリのプロトコルもこの形式を踏襲しているものが大多数で、ライブラリの付加価値はスキーマの管理方法の標準化だったりデータ型ごとのコーデックの標準化だったり高速な実装の再利用だったりです。でもソフトウェアは厳密な汎用性を求めると「なんにでも対応する」ためにとんでもない量のコードになりがちです。例えばライブラリの多くはデータ型ごとのエンコード・デコード方法を標準化したりもしていますが、こういうライブラリは「なんにでも対応する」ために一生使わないようなデータ型も背負い込むことになり組み込みでは邪魔にもなると。そういうのが嫌だったら自分で書いちゃった方が早いかもよ、という話です。実際、TLV の実装はそんなに大変じゃないです。

車輪の再発明?いやでも生き物だって収斂進化みたいなものがあるし少しぐらいいいんじゃないかな。

なんにしても同じような問題を持っている人がたくさんいることがわかってよかった。

Comments

No comments yet. Why don’t you start the discussion?

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

This site uses Akismet to reduce spam. Learn how your comment data is processed.