僕は大学でHPCやコンピュータアーキテクチャを専攻する身であり、そのような分野では基本的にはISAを直に考え、HW Specificなネイティブコードについて考えたり扱うことが多い。
当然ネイティブコードの方が早いように思われるのかもしれないが、インターネットを介して多くのアプリケーションがやり取りされる今日、一つのアプリケーションでも複数のアーキテクチャに対してサポートしなければならないようになってきた。
今までのPCアプリケーション開発ではi386をターゲットにしてコンパイルしていたかもしれないが、これからはARMノートPCが来る。そして当然ARMノートPCの上でも性能は要求される。常にi386コードをエミュレーションして動作させるのはおそらくユーザーが納得しないだろう。
そこで重宝されるのがインターネット上での頒布はバイトコードで行う手法だと考えている。バイトコードをアーキテクチャから独立した形式で設計し、IA-64でもARMでもMIPSでももしかしたらこれから登場するかもしれないアーキテクチャにも対応させるのだ。
元々このアイディアはAndroidが実装していた。Android開発ではDalvikアーキテクチャという仮想的なアーキテクチャの上でのバイトコードを出力し、それをAndroid上でJITコンパイルで実行していた。これをLolipopになってからはARTという技術が導入されAOTコンパイルを可能にし、実行速度を改善した。しかしインストール時やアップデート時のコンパイルが必要となるため、この部分に時間がかかり、結局JIT形式に落ち着いたようだ。
バイトコードを利用するのはただ単に異なるアーキテクチャに対応させるためだけが目的ではない。たとえばARMで言えばNEON、Intelで言えばAVX/SSEのベクトル命令は性能を上げる上で利用したいものだ。しかし、これらは同じARMやx86_64でもプロセッサのグレードや想定使途などで細かく仕様が異なる。これを吸収することが出来るのがバイトコードなのではないかと考えているのだ。
SIMDを使う以外にもこれからのプロセッサはキャッシュよりもローカルメモリを使うようになるのではないかと思っているので、このローカルメモリのサイズの違いに合わせたネイティブコードを出力できるという点でもJIT/AOTは優れていると感じる。
(さらに抽象度を上げて言えば、ハードウェアスペシフィックな最適化を行うことが可能ということがとても良いのだ)
さっきからバイトコードと言っているものの、単に機械語よりは抽象度が高いが、高機能ではない中間表現として扱っているだけで、JavaバイトコードとかDalvikバイトコードが良いとか言っているわけではない。個人的にはLLVMのbcファイルの”LLVMビットコード”を推している。