SjLj-EH 遅すぎ

どうもプロファイリングのやり方がマズかったようです。
VC++でもg++でも似た傾向になるだろうと考えていたのですが、Cygwin/MinGWのSjLj例外処理が非常に遅く、プログラム全体のパフォーマンスを低下させていました。
特にCygwinの場合は異常に遅いです。おそらくpthreadエミュレーション絡みの問題だと思います。


というわけで、プロファイラに頼るのは諦めて、地道に調整することに、、、。
昨日の1文字read()に対する最適化は結構効いたので、その辺りをメインでやりました。
Boost.Iostreamsで1文字読み出す場合、boost::iostreams::get()という関数があります。
これは、

srcの型 動作
istream src.get()
streambuf src.sbumpc()
Source src.read(s,1)

という動作になっていて、通常はカスタマイズできません。
どうしてもカスタマイズしたい場合は、

namespace boost { namespace iostreams {

template<>
struct operations<hamigaki::iostreams::file_source>
{
    static std::char_traits<char>::int_type
    get(hamigaki::iostreams::file_source& t)
    {
        return t.get();
    }

    static std::streamsize
    read(hamigaki::iostreams::file_source& t, char* s, std::streamsize n)
    {
        return t.read(s, n);
    }

    static std::streampos seek(
        hamigaki::iostreams::file_source& t,
        stream_offset off, BOOST_IOS::seekdir way, BOOST_IOS::openmode)
    {
        return t.seek(off, way);
    }

    static void close(
        hamigaki::iostreams::file_source& t, BOOST_IOS::openmode which)
    {
        detail::close_impl<closable_tag>::close(t, which);
    }
};

} } // End namespaces iostreams, boost.

のようにすればできますが、このSourceにアダプタを被せたとたん、get()を呼んでくれなくなります。
これは、Boost.Iostreamsがget()のカスタマイズを想定していない(getable_tagのようなものがない)ので、どうしようもありません。
このため、実質boost::iostreams::get()は使い物にならず、1文字ずつ処理したい場合は、自前でバッファリングすることが必要になります。
bit_filter.hppの差分
これで1秒短縮できました。

ツール 時間
UNLHA32.DLL 2.2秒
lzh_file_source(昨日のバージョン) 5.2秒
lzh_file_source(バッファリング版) 4.2秒

試しに入力ファイルの内容を全部メモリに読み込んで、null_sinkに書き出すテストをしてみましたが、タイムはほとんど変わらず、I/O周りではこれ以上縮みそうにありません。
Boost.Iostreamsの作り上、この辺りが限界かもしれません。


ちなみに、なぜかFedoraCore5 on VMwareだと2.7秒でした。謎です。