MessagePackとProtocol Buffersを試してみた

Visual C++ 2005でMessagePackとProtocol Buffersを試してみた。

MessagePack

インストール

http://msgpack.sourceforge.jp/ から最新版(3/10の時点ではmsgpack-0.4.2.tar.gz)をダウンロードし、適当な場所に展開する。
プロジェクトファイルは付属してないので作成した。
http://github.com/firewood/test/blob/master/msgpack_vc8.sln
http://github.com/firewood/test/blob/master/msgpack_vc8.vcproj
c/msgpack/zone.hに以下の部分がある場合は削る。(msgpack/sysdep.hで吸収しているので不要)
#include
#include
プロジェクトファイルを開き、バッチビルドでDebugとRelease両方をビルドしておく。これでフォルダlib以下にmsgpack.lib(リリース版ライブラリ)とmsgpackd.lib(デバッグ版ライブラリ)ができる。

以下インストールしたフォルダをC:\msgpackとする。
VC++の開発環境の「ツール→オプション」のダイアログを開く。「プロジェクトおよびソリューション」の「VC++ディレクトリ」の「インクルードファイル」の欄に
C:\msgpack\cpp
C:\msgpack\c
C:\msgpack
を追加する。
「ライブラリファイル」の欄に
C:\msgpack\lib
を追加する。

使い方

以下のようにしてヘッダとライブラリを追加する。(msgpack.vcprojを自分のプロジェクトに追加する必要はない)
#include
#pragma comment(lib, "ws2_32.lib")
#ifdef _DEBUG
#pragma comment(lib, "msgpackd.lib")
#else
#pragma comment(lib, "msgpack.lib")
#endif

オブジェクト生成→ファイルへ保存→ファイルから読み込み→オブジェクトへ戻すというお手軽な例を書いてみた。
http://github.com/firewood/test/blob/master/MsgPackTest.cpp
http://github.com/firewood/test/blob/master/MsgPackTest.sln
http://github.com/firewood/test/blob/master/MsgPackTest.vcproj
なお公式APIドキュメントはこれ

Protocol Buffers

インストール

Google CodeのDownloadのとこから最新版(3/10の時点ではprotobuf-2.3.0.zip)をダウンロードし、適当な場所に展開する。
付属のプロジェクトファイルvsprojects/protobuf.slnにより、protoc.exeやlibprotobuf.libがビルドできる。

もしプロジェクトファイル(libprotobuf.vcproj)を自分のプロジェクトに含めないで利用する場合には、ライブラリの名前がデバッグとリリースで重複するので、プロジェクトlibprotobufのプロパティを開き、ライブラリアンの出力ファイルを$(OutDir)\$(ProjectName)d.libのように変更しておく。

以下インストールしたフォルダをC:\protobufとする。
VC++の開発環境の「ツール→オプション」のダイアログを開く。「プロジェクトおよびソリューション」の「VC++ディレクトリ」の「インクルードファイル」の欄に
C:\protobuf\src
を追加する。
「ライブラリファイル」の欄に
C:\protobuf\vsprojects\Debug
C:\protobuf\vsprojects\Release
を追加する。
「実行ファイル」の欄に
C:\protobuf\vsprojects\Release
を追加する。(protoc.exeを使用する)

Protocol Buffersでは.protoという定義ファイルをprotocという独自のコンパイラコンパイルするようになっているので、これのカスタムビルドルールを追加しておく。
カスタムビルドルールが存在しない場合、.protoファイルを追加するとダイアログで聞いてくるので、その場で作ることもできるが、参考までに以下に置いておく。
http://github.com/firewood/test/blob/master/ProtocolBuffers.rules
このファイルをVCのインストールディレクトリ(C:\Program Files\VisualStudio2005\VC\VCProjectDefaultsみたいなところ、masm.rulesとかがあるはず)に置いてから、プロジェクトを右クリックして「カスタムビルド規則」を選び、「既存ファイルの追加」で追加しておく。VCProjectDefaultsに置いておくとプロジェクト毎に指定しなくてよい。

使い方

定義ファイルHoge.protoを利用する場合、以下のような感じ。
#include "Hoge.pb.h"
#ifdef _DEBUG
#pragma comment(lib, "libprotobufd.lib")
#else
#pragma comment(lib, "libprotobuf.lib")
#endif

こちらもオブジェクト生成→ファイルへ保存→ファイルから読み込み→オブジェクトへ戻すという例。
http://github.com/firewood/test/blob/master/Hoge.proto
http://github.com/firewood/test/blob/master/ProtoBufTest.cpp
http://github.com/firewood/test/blob/master/ProtoBufTest.sln
http://github.com/firewood/test/blob/master/ProtoBufTest.vcproj
チュートリアルで十分な気はする。

感想

MessagePackは低レベル関数が最初から見えているので小回りがきくのかなと。メンバの格納順序を気にしたくない(こんな感じ http://github.com/firewood/test/blob/master/Deserial.cpp)みたいなときにカスタムデシリアライザを書くこともできる。
Protocol Buffersは、デシリアライズしたオブジェクトがそのまま使えるので便利。しかしいろんな型のものを突っ込むのはどうやったらいいのかわからない。

PC環境検討会

よくわからない会合に行ってきた。Windows3台、OSX4台で、OSX率高し。Macは10年くらい使ってないので参考になった。

スタイル

どこでもgenericな環境 or カスタマイズばりばり、という軸だと私は自前の常駐アプリが何本か走ってたりして後者なのだが、OSや場所にしばられないようにしようとすると必然的に前者になる。まかーの人たちは便利なUNIXコンソールとしてOSXを使ってた感じ。Windowsをコンソールにするときに困るのはマルチスクリーン(仮想デスクトップ)が悲惨とか、cmd.exeよりCygwinとか。

メモとファイル

私はよく1つのファイルにどんどん追記していくのだけど、日付毎に1ファイルにしたほうが検索しやすそうだった。作業日報とか作るときに便利。

ツリーメモ、TODO管理

4人くらいFreeMindを使ってたようだ。いわゆるアウトラインプロセッサは書き方を強制されるというイメージがあったのだけど、使いたいように使えばいいのかなと。議事録を取っている様子を見て、これは是非使いたいと思ったが、キーカスタマイズは必須そうである。
横に長くなったらどうすんだろと思ったら長文モードとかもあった。

sync

sa-yさんの環境(複数OS+Dropbox共有+自動分配スクリプト)は素晴らしい。近い環境になった暁には真似したい。
ごにいさんevernoteに名刺とか何でもつっこむというのも良さそうだった。ただWindowsと日本語への対応はまだ発展途上ぽい。

エディタ

isshikiさんと共鳴しすぎた。エディタとかよりもこの辺の方がシンクロ率高い気がするが。ちなみにWE LOVE WIZARDRYとALL OVER XANADUは家宝ですよ(脱線
エクスプローラの右クリックからGREPできる環境に慣れすぎていてWZが捨てられないのだがあまりにも非標準すぎて困る。もう少しviを使えるようになろう。

キーremap

tekezoさんのこだわりはすごい。カスタマイズが日常化していて実に楽しそうだ。OSXの素晴らしいところは見た目ではなくドライバ周り(フックとかPnPとか)だと思う自分。
XKeymacsがctrlキーがロックするとかいう話があったが、ユーザーモードだけでやろうとするとどうしてもバグるのかも。Windowsだとキーのカスタマイズ方法は何種類もあるようだ(参考)。
Linuxの日本語環境にはみんなご不満の様子。

開発環境

isshikiさんのエディタとか開発の流れの話。ペアプロとかしない限り、他人がどうやって作ってるのかってなかなかわからないものである。Unityとか見てるとテキストエディタでちまちま作るってのは趣味ですら絶滅しつつあるのかなあとか。Unreal Development Kitとかも似てる印象。

ファイルの日付

そういえばファイルの更新日付って気にしない人の方が多いのかなあと思う。私はエクスプローラは常に詳細表示で、更新日付で検索をかけることが多いのだが、cvsやgitでアップデートをかけるとデフォルトで(commitされた日付ではなく)取得した日付になる。他の人は新しいかどうかってどうやって判断してるんだろ。

いやほんと環境といっても色々ありますね。Zinniaさん良い会ありがとうございました。

LRUSet

キャッシュのデータ構造について。「キャッシュのデータ構造 with Boost.MultiIndex」と「slist LRUMap」でできるっぽいので、それぞれでLRUSetを実装してみた。GetかAddするとキューの末尾に並び替えられるというもの。

まずBoost.MultiIndexのほう。http://github.com/firewood/test/blob/master/MultiIndexTest.cpp
modify()でlast_accessメンバを更新すると自動的にソートしなおされる。この手軽さと強力さはすばらしい。ただVC++だとエラーメッセージからエラーの原因をつかむのが難しかったりする(「'boost::multi_index::detail::bidir_node_iterator' から 'boost::multi_index::detail::bidir_node_iterator' に変換できません」とか)。

でstd::setとslistの組み合わせのほう。http://github.com/firewood/test/blob/master/LRUSet.cpp
set+slistを実現するためにsetにはノード構造体のポインタを入れることにした。ノード構造体はnextとvalueを保持していて、setは次のノードの値(next->value)でソートするという変則仕様。リンクチェーンの更新はnextとvalue、自分と前後で計6箇所書き換えている。kinabaさんの元のソースではポインタの差し替えをしているのだが、ポインタのsetにおけるポインタは要素の値であり直接書き換えられない(ポインタのポインタのsetにすれば差し替え可能になるが、余計なメモリを消費するくらいなら双方向リストにしたほうがよい)。そのためわざわざ前のノードのポインタも取得している。実用性はないがパズルとしては楽しめた。

DWARF の行情報を読む

DWARF の行情報を読むのをWindowsでやってみた。ELFをPEにしただけ。
http://github.com/firewood/test/blob/master/addr2line.cpp

今のMinGW-GCCデバッグ情報はDWARF2がデフォルトのようで*1、-gをつけると.debug_lineが付加されるようになる。*2

PEだとIMAGE_SECTION_HEADER内のセクション名には8文字しか入らず、ポインタらしき名前がついている。バイナリの末尾に文字列テーブルがあるが、そこのオフセット値がどこに格納されてるかわからなかったので、とりあえずきめうちで/61をダンプするようにした。

これの実行結果は

extern int printf(const char *, ...);
int main(int argc, char *argv[]) 
{
    printf("Hello, world.\n");
    return 0;
}

こんな感じになった。

hello.c:3: 004013F0
hello.c:3: 00401401
hello.c:4: 00401406
hello.c:5: 00401412
hello.c:6: 00401417
hello.c:6: 00401420

ちょっとがんばればVC++の「混合モードを表示」みたいなのができる。超がんばればデバッガも作れる…かもしれない。

*1:以前はstabsのみサポートだった気がする

*2:例外のスタック巻き戻し方式でSJLJとDWARF2があるが、いずれもデフォルトは-gdwarf2のようである

SICP自習

SICP Lite #9に行かなかったので自習。
DrSchemeにてある範囲の素数を求めて、結果(個数)と実行時間を表示する。divides?とprime?はあるとして

(define (search-for-primes start end)
  (define (next n)
    (+ n (if (divides? 2 n) 1 2)))
  (define (loop start end result)
    (if (> start end)
        result
        (loop (next start) end (+ result (if (prime? start) 1 0)))))
  (loop start end 0))

(define (timed-search start end)
  (define (print-result result time)
    (print (string-append "prime count: " (number->string result)))
    (newline)
    (print (string-append "exec time: " (number->string time))))
  (define (loop start end start-tick)
    (print-result (search-for-primes start end) (- (current-process-milliseconds) start-tick)))
  (loop start end (current-process-milliseconds)))

ちょうどリーマン予想NHKスペシャルを見たところで、級数からπを求めるとかいうタイムリーなトピックがあって楽しい。(習ったのかもしれないが完全に忘れてる)

情報科学苦手の会

twitterで見かけて参加。

  • 具体的なプログラムは組まずに
  • 参加者各自が苦手な事について自由に雑談や議論を交わしたり
  • 苦手なことについて自習したり
  • 教えられる人が居れば積極的に教えてあげてください。
  • 今勉強していることをスライドで発表する

というイベントとのことで、その場で聞くというスタイルは良いと思った。
以下時系列イベント

自己紹介

せっかくnyaxtさんがいたのに3Dが苦手と言うのを忘れた。しかしながら、知りたいことが漠然としすぎていて、もう少し何か書いてみようと思った。

C++の話 shinh

G++が吐くアセンブリコードの話。多重継承したときのvtableの内容とか、virtual関数のポインタを取ると中身がただのindex値とか(VCはポインタとのこと)。例外(SjljとDWARF)でどうやってスタックを巻き戻すのかとか。
○○になってますよ、という説明で、はいそうですかと納得するのは騙されやすいタイプ(探究心が足りないという意味だと思われ)。

ホワイトハウスへの道 yuyarin

まずCDNの話。ホワイトハウスのwebサーバにアクセスすると、最も近いAkamaiのサーバを見てるだけかもとか。次にGoogle Public DNSとIP Anycastについて。物理的に別のサーバに同じアドレスを振り、最も近いところにアクセスするという点ではCDNに似てると思った。
以前DNS応答時間を調べたことがあって、結構な頻度で数十msくらいかかっており、自前でキャッシュしたらそこそこ速くなったりした。Google Public DNS使うと劇速というのは納得できる話。
ネタ的には、ホワイトハウス内にはwebサーバは一台もないから「本物」には到達不能ではないかとか。

diffのアルゴリズム cubicdaiya

編集距離について。図でなんとなくわかった気になったけど対角線の距離のところで挫折。最悪値が全削除→全追加で、そこから最も遠い点を求めていくみたいな感じなのかな。
WinDiffは追加・削除のほかに移動も教えてくれるのだが、これは質問したら「hunk(差分)に対してdiffを取ればわかる」との答え。なるほど。

expornentialの実装 herumi

floatのe^xの高速実行について。floatの内部形式が(1+n)の形なので、それをうまく変形するとテーブル引きできるようになったという話。
doubleだと表が爆発するんじゃ?という質問に対しては、e(a+b)=e(a)e(b)であり、上位ビット群のみのテーブル、中位ビット群のみのテーブル、下位ビット群のみのテーブルみたいに分割していけるので実装可能とのこと。
あとx86のdoubleは内部で80bitで扱ってる云々の話が出てWikipedia見てみたところ、8087はIEEE754の原型になり、80387で完全準拠とのことだ。ただしSSEの命令の一部の誤差は非準拠らしい。あと改定されてIEEE754Rになるぽい。

MVCの次は? NetPenguin

MVCの解釈が人により違うとか、じゃあなぜMVCが誤解されてるのかとか、誤解されなければよいだけでは?とか色々突っ込みが入ってこれは地雷(みんなMVCの話が好きすぎる)ということに落ち着いた。

SMPカーネル syuu1228

カーネルをSMP対応するときの作業内容など。スケジューラは、Hyper-threadingやNUMAなど固有の特性を知っておかないとロックしたりするとか。

goのアセンブラ ucq

見た目はx86っぽいアセンブラだけどビルドするとわけわからんことになっているらしい。コマンドが8a。

L3以下のIPの話 yuyarin

1000BASE-TXの変調方式の話など。素晴らしき低レイヤの世界。

FPGAとは何ぞや firewood

Google GroupでshinhさんがFPGAわからんと書いてたので、プレゼン聞きながらその場で書いた。はよピザ食わせろという殺伐とした雰囲気の中、ThinkPadが固まり再起動してさらに待たせることになった。HDLは10行くらいしか書いたことなくて嘘を言ってないかどきどきしながら発表した。学校の演習でCPUを書いた人とかいて釈迦に説法感ばりばりではあった。

個人的にはFLTVの時もそうだったけど微妙にカオスな感じがクラブ活動みたいで面白かった。
開催前は小さいQ→Aを繰り返す会みたいな感じにしようという思惑があったのかもしれないのだけど、始まってみると個々のトピックでは得意な人もいるために、苦手な人は埋もれて得意な人が前に出るみたいな感じになってしまった面はあったかと思う。(どこが苦手なんだみたいな突っ込みが何回かあった)ただ、会のタイトルが苦手ということで、素朴な質問でもOKという雰囲気ではあったと思う。そこは特に良かった。開催感謝です。

ONE PIECEの新聞広告

新聞の朝刊にONE PIECEの全面広告が9面が載っていたのだが、家庭用スキャナを使ったのかと思うくらいの画質で驚いた。
スキャニングのジャギーがくっくり印刷されてて、線の力が削がれてる。

それにしても広告の比率高いなあ。紙面の6割は広告って感じ。