世界を動かす技術を、日本語で。

x86エミュレーターチームがエミュレーション中にあまりにも悪いコードを見つけて修正した時

概要

  • Windowsのx86-32エミュレータでの珍事件の紹介
  • バイナリ変換によるJIT的な高速化の説明
  • 64KBのメモリ初期化で起きた非効率な最適化事例
  • チームが特別な変換コードを追加した経緯
  • 著者Raymondの経歴とThe Old New Thingについて

Windowsエミュレータとバイナリ変換の逸話

  • Windowsは過去に x86-32以外のプロセッサ 上で x86-32エミュレーション を提供
  • このエミュレータは バイナリ変換 を用い、 ネイティブコード生成 による高速化を実現
    • x86-32コードを バイトコード と見なし、エミュレータが JITコンパイラ の役割
  • あるプログラムが 約64KBのスタックメモリ確保と初期化 を必要とする事例発生
    • 通常は スタックプローブ で空き確認後、スタックポインタを65536減算
    • 小さなループでメモリ初期化が一般的
  • 使用された コンパイラ はループを展開し、
    • 65,536回分の「メモリへ1バイト書き込み」命令 を個別に生成
    • 各命令は 4バイト、合計で 256KBのコード が64KBのデータ初期化に使用
  • エミュレータ開発チームはこの非効率さに衝撃を受け、
    • 変換器に特別な処理 を追加し、該当関数を 効率的なループ に置換

Raymond ChenとThe Old New Thing

  • 著者 Raymond Chen30年以上Windowsの進化 に関与
  • 2003年にWebサイト The Old New Thing を開設
    • サイトは予想以上の人気を獲得し、本人も驚愕
    • サイト内容をもとに書籍 The Old New Thing (Addison Wesley 2007) も出版
  • 時折 Windows Dev Docs Twitter アカウントにも登場
    • 有益ではないが面白いWindowsの裏話を投稿

Hackerたちの意見

最近、LinuxコミュニティでProtonやWineが注目されてきてるから、こういうことが増えてきた気がする。いくつかのゲーム(エルデンリングが思い浮かぶけど)って、発売時にPC版の移植がひどくて、互換性レイヤーがパフォーマンスを改善するためのホットフィックスを取り入れたりするんだよね。一方で、元のプラットフォームのユーザーはまだ苦しんでるっていう。

GPUドライバーも同じことをやってる気がする。ゲームごとの調整がたくさん含まれてて、動作を速くするためのものなんだよね。外部コンポーネントがソフトウェアに依存しないはずなのに、消費者が直すべき問題を解決しようとして余計なものを含めちゃってる感じがして、ちょっと脆弱なやり方だなと思う。

GPUドライバーパッケージは、悪いゲームエンジンのコーディングに対する回避策が山ほど詰まってる。Nvidiaの社員が言ってたけど、古いマシンでちょっとフレームを増やす簡単な方法は、ゲームの実行ファイル名をhl2.exeに変更することなんだって。

GPUドライバーのアップデートの大部分は、実際にはそういうもので、Windowsのアップデートも同じ。Windows 95では、SimCityのバグを修正するためにパッチが当てられたんだよね。

そうそう、誰かがWindowsドライバーがやってるのと同じような回避策をLinuxでもやる必要があるんだ。翻訳レイヤーはそのための良い場所だと思うよ。例えば、https://github.com/HansKristian-Work/vkd3d-proton/blob/938d7...を見てみて。

ベッティングアルファが問題のネイティブアーキテクチャだったみたい。サポートが一番良さそうだったね。

エミュレーション中に修正されたってことだね。これは、エミュレーションループの実行中に修正が見つかって適用されたわけじゃなくて、エミュレーションループの実行中に修正が適用されるようになったってこと。つまり、エミュレーションコードの逃げ道ができたってことだね。

トランスメタの人たちから、彼らのトランスレーターがMicrosoft Windows自体で発見された恐ろしいバグを修正するための特別な最適化でいっぱいだったって話を聞いたことがあるよ。

そういえば、それどうなったんだろう?

シムシティには、MicrosoftがWindows 95でパッチを当てたread-after-freeバグがあったんだ。それは、マキシスが修正するよりも顧客にとってはずっと楽だった。ゲームのコピーを交換する必要があったかもしれないからね。

グラフィックドライバーもこれをよくやってる気がする。少なくとも、特定のゲームに対して特別な最適化をしてるよね。たぶん、ゲーム開発者が自分たちでちゃんと最適化してない設定や機能を調整してるんだろうな。

一番面白いのは、確か彼らがWindows 3.11のメモリアロケーターを丸ごと持ってきて動かしたってことだよね。OSレベルでのアロケーションの仕組みはあまり理解してないけど、こういう問題に特化したdgVoodooやdxWrapperみたいなラッパーがないのは意外だな。古いWindowsゲーム(最初のNeed for Speed 1-4とか)が、かなり大胆なメモリ管理戦略のせいで現代のOSでは動かないってのが結構あるんだよね。

Hacker Newsで議論の続きを見る