続 ハフマンデコードの改良

既にLHAとはほとんど関係なくなってますが、プロファイルをとるときに-O2を指定していなかったので、もう一度。

  %   cumulative   self              self     total           
 time   seconds   seconds    calls   s/call   s/call  name    
 46.93     12.54    12.54                             _Unwind_SjLj_Register
 22.75     18.62     6.08                             _Unwind_SjLj_Unregister

がーん。例外処理で7割も食ってるじゃないですか!
これはループの奥深くに問題がある証拠です。
どのデストラクタが悪さしているかはまだ分かりませんが、試しに呼び出しの一番奥深くにあるinput_bit_filter::get_bit()の例外送出をコメントアウトすると、上の二つは消えました。(当然このままだとバグありです)
現状のタイムは以下の通りです。

ツール 時間
UNLHA32.DLL(測り直し) 2.2秒
lzh_file_source(昨日のバージョン) 7.5秒
lzh_file_source(今日いろいろ頑張った版) 5.2秒
lzh_file_source(エラー無視版) 4.9秒

残念ながら(?)、UNLHA32は計測ミスで実際もっと速いことが分かりました。
追いついたと思ったら、まだ倍以上時間がかかっています。


今日の修正:
bit_filter.hppの差分
lzhuff.hppの差分
あと、他にも

  • boost::iostreams::file_source::read()で1文字だけ読み込むとき(get()など)は、sbumpc()を呼ぶように最適化する
  • VC++なら/GL(プログラム全体の最適化)オプションを使う(というか付け忘れていた)

が効果ありました。
Boostのヘッダを書き換えるわけにもいかないので、get()用の最適化はリネームしてから使っています。
boost::iostreams::get()だけカスタマイズできれば良いのですが、Boost.Iostreamsのカスタマイズ機構はあらゆる操作をまとめてカスタマイズしてしまうので面倒なんですよね。
streambufのsbumpc()とsgetn()は結構速度差があるだけに痛いところです。