Open3

warp: TLB実装最適化アイデアのメモ

okuokuokuoku

v86は全てのx86メモリアクセスをTLB解決 〜 有効性判定 〜 実際のメモリアクセス を行うコードに変換している。

IBM の Optimizing memory translation emulation in full system emulators は、このような一般的なケースを考察している https://research.ibm.com/publications/optimizing-memory-translation-emulation-in-full-system-emulators

v86(や、MAME)はTLBをシングルレベルにしている。CPUがアドレス可能な32bit空間全体をカバーするTLB構造体を用意したとしても数MiBに収まるためこれが可能になる。64bit空間をサポートするためには、適当な単位に分割した上で、一般的なset associativeとかdirect map法を取ることになると考えられる。

64bitアプリケーションをサポートすることを考えると、全てのread/writeでこれを行うのは重い気がする。現代的なCPUでは、キャッシュに載った値を読んで分岐しないと判断することはほぼノーコストで行えるが、命令数が増えると命令キャッシュ(通常のCPUでは64KiBとかしか無い)を圧迫してしまいあんまり早くできない。

warpでは、汎用のCPUをエミュレーションするのではなく、(ブラウザ上では、)ABIが既知のWebAssemblyバイナリを "インストゥルメントされた" WebAssembly に変換して実行するため、もしかしたら別の新しいテクニックが考えられるかもしれない。

okuokuokuoku

クラスタ化

直ぐ思いつく最適化は、super block内のメモリ命令が附近を読むと保証されているならばかなりの確率でチェックを省略できることだろう。

例えはポインタの指す先が不幸にもページ境界の末尾だったとしても、 常に連続する2ページをpage inする と約束すれば、容易に最初のpage faultから1ページぶんは(直近では)faultしないことが保証できる。

現実的なユースケースでは、他のスレッドからページアウトされないように何らかの方法で保護する必要があるが、それはv86のように各命令でTLBをチェックする実装でも同様になる。

okuokuokuoku

Remapping / Colouring

そもそもTLB経由でアクセスされるメモリの大半はヒープメモリで、その利用パターンは非常にシンプルなものになる -- 単に sbrk で有効なアドレス範囲が成長するだけで、大半のユースケースではアドレス空間に "穴" は空かない。

じゃぁメモリ空間の断片ごとにアドレスのリマッピングを行って直接アクセスさせる方が有利なのではないだろうか。。superblock毎にどの空間をアクセスするかを静的に決めておき、呼出し時にそれらのオフセットを渡す。

重要な例外はスレッドのスタックで、スタックオーバーフローを良く検出するためにアドレス空間に穴が空けられる。要するに 命令をスレッドのスタックにアクセスするものとそうでないものに分類し、スレッドスタックの操作はTLB lookupを省略 できないだろうか。