xv6のバイナリをISSで実行しているが、最初のバイナリのロードでもの凄く時間がかかっている。 ロードだけで1分くらいはかかっているように感じる。
まずは、Google Perftoolsを使って、何が発生しているのかを調査した。 Google Perftoolsはもうシミュレータのバイナリに組込めるようにcmakeを作っているので、オプションを変えてビルドするだけだ。
cmake -DUSE_GPERF .
make
できた。これで、実行するだけで性能解析を行ってくれる。
CPUPROFILE=/tmp/swimmer.prof ~/swimmer_riscv/build_mips/swimmer_mips --binfile kernel --debug --out debug.log --debug_func --debug_gvar --init_pc 0x80100000 pprof ~/swimmer_riscv/build_mips/swimmer_mips /tmp/swimmer.prof
これで、解析そのものはできる。まずはtopからだ。
$ pprof ~/swimmer_riscv/build_mips/swimmer_mips /tmp/swimmer.prof Using local file /home/vagrant/swimmer_riscv/build_mips/swimmer_mips. Using local file /tmp/swimmer.prof. Welcome to pprof! For help, type 'help'. (pprof) top Total: 7356 samples 1285 17.5% 17.5% 6277 85.3% Memory::InsertMemTable 1100 15.0% 32.4% 1311 17.8% __gnu_cxx::__normal_iterator::operator++ 1054 14.3% 46.8% 1325 18.0% __gnu_cxx::operator!= 831 11.3% 58.0% 831 11.3% __gnu_cxx::__normal_iterator::__normal_iterator 813 11.1% 69.1% 1259 17.1% std::vector::end 671 9.1% 78.2% 671 9.1% MemoryBlock::GetBaseAddr 631 8.6% 86.8% 631 8.6% MemoryBlock::GetBlockSize 436 5.9% 92.7% 436 5.9% __gnu_cxx::__normal_iterator::base 431 5.9% 98.6% 431 5.9% __gnu_cxx::__normal_iterator::operator* 26 0.4% 98.9% 124 1.7% Memory::SearchMemTable
あー、やっぱり、バイナリをメモリに格納するところで時間がかかっている。特にInsertMemTableは、ベクタを探索して、適切なブロック見つけ出し、発見できなければ新しいブロックを探索するというようになっているので、最初のバイナリが非常に大きければ、それだけ時間がかかる。 これは、もうちょっと別の方法で削減できないかなあ。