パフォーマンスを気にしているならlexical_castを使わない方がいい

tkngさんの日記「C++で例外を使ったプログラムをうまく書くにはどうすればいいのか」を読んで、
パフォーマンスを気にするのであれば「文字列=>整数変換」にboost::lexical_castを使わない方がいいんじゃないかと思ったのでその実験結果メモ。


C++では文字列整数変換を行う時に3種類ぐらいの方法がある。
(もちろん自分でstrtol相当を書くこともできるし、みんな一度は自分で実装してそうだけど・・・)

  1. strtolを使う方法
  2. stringstreamを使う方法
  3. boost::lexical_castを使う方法


そもそもboost::lexical_castを使う場合は、中でstringstreamを使ってるというを聞いたことがあって、
オブジェクトのコピー等が頻発して非常に遅い思っていた。
なので、どのぐらい遅いのか、ということを実際にベンチマークを取って計測してみた。


実験に使ったプログラムは二種類。

  1. テストデータを出力するプログラム
  2. 上記3種類の方法のベンチーマークプログラム


実行結果 (g++ バージョン: 4.4.3 コンパイルオプション: g++ -O2 -DNODEBUG strtol_bench.cc -o strtol_bench)

strtolを使った方法 0.06秒
stringstreamを使った方法 0.67秒
boost::lexical_castを使った方法 0.42秒


ということで、strtolを使った方法では約5 〜 8倍boost::lexical_castよりも速い。


strtolを使った方法では、エラー処理等をいれてないからじゃないか?という批判があるかもしれないので、
一応プログラムの方ではエラー処理を入れて計測している。
stringstreamよりboost::lexical_castの方が高速なのは、boostならではのチューニングがされているということなんだと思う。


C++でもパフォーマンスが問題とする時と、問題としない時(LLを使っても良いが、ライブラリの関係でC++で書いた方が早いという時)があると思っていて、
パフォーマンスが気にならない場合は、boost::lexical_castを使って富豪的に書いちゃってもいいんじゃないかなーと思う。


でもライブラリ書くならパフォーマンス、わかりやすさ、どちらも取るべきだと思うので、そういった場合にboost::lexical_castは適さない、というのが結論。


あ、でも↑のは例題の解答なので、質問の本題には答えられていません。
本題の方は、プログラム例の方で書いていますが、こういった場合僕ならstrtol+(char_numを格納できる)新しい例外クラスを作ってそれを投げます。

また、もしバイナリでシリアライズが可能であればバイナリでシリアライズした方が高速なのでそちらをおすすめします。

MacBook Air 11インチ欲しい!