自作RISC-Vエミュレータの性能解析続き。私はWSL1を使用しているので、Rustの性能解析ツールflamegraph
を使用することができない(どうもLinuxのツールが必要で、これがWSL1では使用できないようだ)。
AWS上に急遽Rustの環境を構築し、そこでflamegraph
による性能解析を行った。Dhrystoneを実行し、flamegraph
による性能解析を実行した。
$ cargo flamegraph --bin dydra -- --machine sifive_u --elf-file /home/msyksphinz/work/riscv/freedom-e-sdk/software/dhrystone/release/dhrystone.elf
これ取得したflamegraph
が以下である。...なんかHashMapの処理がほとんどだな...RustのHashMapが遅いと聞いていたが、これは処理のほとんどがHashMapではないか。
HashMapがなぜこんなに遅いのだろう、ということでいろいろ調べていたのだが、以下のようなそのまんまなQ&Aを発見した。
代替手段としてはFnvHashMapというのがあるらしい。じゃあとりあえずこれを使えば高速になるのかな?
現在の実装をFnvHashMap
を使って置き換えてみた。
diff --git a/src/emu_env.rs b/src/emu_env.rs index 163a554..7525eeb 100644 --- a/src/emu_env.rs +++ b/src/emu_env.rs @@ -2,7 +2,7 @@ use std::cell::RefCell; use std::rc::Rc; use mmap::{MapOption, MemoryMap}; -use std::collections::HashMap; +use fnv::FnvHashMap; use std::mem; use crate::elf_loader::{ELFLoader}; @@ -68,7 +68,7 @@ pub struct EmuEnv { pub m_prologue_epilogue_mem: MemoryMap, pub m_guest_mem: MemoryMap, - pub m_tb_text_hashmap: HashMap<u64, (usize, Rc<RefCell<MemoryMap>>)>, + pub m_tb_text_hashmap: FnvHashMap<u64, (usize, Rc<RefCell<MemoryMap>>)>, pub m_curr_tb_text_mem: Rc<RefCell<MemoryMap>>, pub m_host_prologue: [u8; 15], @@ -167,7 +167,7 @@ impl EmuEnv { Ok(m) => m, Err(e) => panic!("Error: {}", e), }, - m_tb_text_hashmap: HashMap::new(), + m_tb_text_hashmap: FnvHashMap::default(), m_curr_tb_text_mem: match MemoryMap::new(1, &[]) { Ok(m) => Rc::new(RefCell::new(m)), Err(e) => panic!("Error: {}", e),
これで同じようにベンチマークを実行してみた。
Simulator | Dhyrstone Time[s] | |
---|---|---|
QEMU-5.1.0 | 0.789 | |
Dydra-a78da94 | FnvHashMap使用 | 3.7488 |
Dydra-6ec3e02 | 初期版 | 5.4504 |
Spike | 28.909 |
うーん、ちょっとだけ速くなった気がする。同じようにflamegraph
を取得してみた。
どっちにしろHashMapが支配的なのは変わっていないよ?もうこれはHashMap自体の使用をやめるべきか。HashMapを使っている部分は変換後TCGを記憶しておくところで、一度登録したTCGをつ年キイ臆しておく必要はなく、キャッシュのように消えても構わないので、普通の配列のようなキャッシュ構成を使うべきなのか?