2018/03/18

[c/c++]protobuf-c (4)

タイトルと違って、C++のprotobufを見ているが、今回までそれをやって、次からprotobuf-cを見に行く予定だ。


では、前回の続きで、protobufのサンプルソースを見る。


まず、書込みから。

https://developers.google.com/protocol-buffers/docs/cpptutorial#writing-a-message

includeやコメントを入れても100行程度だ。


main()は、いきなり「GOOGLE_PROTOBUF_VERIFY_VERSION」というマクロで始まる。
VerifyVersion()を呼ぶマクロで、ライブラリが持つバージョンとヘッダファイルば持つバージョンをチェックして、許容できないバージョンであればabortさせているようだ。

まあ、if文が2つ入っているだけだし、コストはそんなに高くないだろうけど、自動生成したソースでは呼び出すようになっているらしい。
ルールとして最初に呼び出すだけにしておく方がよいように思うのだけど、何か理由があるのかいな?
protocにオプションがあるかと思ったが、各言語への変換はプラグインのようだから、そっちを見ないといかんのか。
思い出したら、見よう。


本体の構造は、シンプルだ。
tutorial::AddressBookのインスタンスを作り、引数で与えたファイル名があればParseFromIstream()で読み込む。
add_people()でAddressBook::Personのインスタンスを作り、それに中身を詰める。
SerializeToOstream()で出力し、メモリ解放APIを呼び出す。

チュートリアルにはシリアライズとして、std::stringとstd::fstreamが載っている。
他にもあるのかとソースを検索しようとしたが、どこがどうつながっているのかわからず断念。。。
C++のリファレンスページを見ると、ParsingSerializerあたりのようだ。
Code / ZeroCopyStream / String / Arrayなのかな?


Peopleに中身を詰めるところは、そんなに凝ったことはしていない。
setterを使って引数に値を指定するか、mutableで直接書き換えるか。


では、読み込みも見よう。
書込みのサンプルに既存ファイルから読み込む箇所があったので、そんなに見なくてもよいかも。

https://developers.google.com/protocol-buffers/docs/cpptutorial#reading-a-message

こちらは70行に満たない。


main()で、引数で与えられたファイル名をParseFromIstream()で読み込んで、あとはリスト出力する関数を呼んで、メモリ解放。
リスト出力するサイズは、peopleがPersonのrepeatedだから、sizeで取得できる。
iteratorみたいなやり方では無くて、引数にindexを指定して取得している。


取り立てて、説明することも無かろう。


あとは、注意事項などが書かれている。

  • tagの数字は書き換えないこと(MUST NOT)
  • required fieldを追加/削除しないこと(MUST NOT)
  • optional fieldとrepeated fieldは削除できる(MAY)
  • optional fieldとrepeated fieldは新規追加できる(MAY)
    • が、tagは新しい数字を割り当てること(MUST)

requredは、削除だけじゃ無くて追加もできないのか。
過去バージョンとの整合性がとれなくなるからかな。


あとは、メッセージのオブジェクトはできるだけ使い回そうとか、tcmallocを使うのも検討しよう・・・って、tcmallocのリンク先がないやん。
これかな?


では、次回からようやくprotobuf-cを見ていくことにしよう。
C++版もいろいろ機能は残っているのだが、全部見ることができそうな気がしないし、シリアライズしてセーブ/ロードができるのだから、もういいだろう。


しかし、これとKey-Value Store型のDBは、まあまあ近い関係にあると思った。
私はlmdbしか使ったことが無いのだけど、あれはデータ構造が平たくなっていると思えばよいか。
データを残すだけだったらlmdbの方が簡単かもしれんが、メモリ上で使っている状態をそのまま保存しておきたいならprotobufの方がプログラムでのデータ構造とセットになっている分、後腐れが無い。
かといって、マルチプロセスでうまいこと運用したいとなるとDBの方がいいだろうし、そう簡単に割り切れるものではないか。

protobufではstd::stringやarrayでも吐き出せるので、KVSのデータの1つとしてprotobufを使うというのはありかもしれんな。

0 件のコメント:

コメントを投稿

コメントありがとうございます。
スパムかもしれない、と私が思ったら、
申し訳ないですが勝手に削除することもあります。