VM言語が一度だけコンパイルされないのはなぜですか?


8

(最初に、コンパイラと仮想マシン(別名)は私にとってまったく未知のフィールドであることを明確にする必要があります)

私が理解しているように、Java / C#/ ...アプリケーションが実行されるたびにVMが呼び出され、中間コード(バイトコード、CILなど)を機械語命令に変換します。

しかし、なぜこの操作を一度だけしか実行できないのですか?


1
インストール時間とは何ですか?
Peter Taylor

3
標準的な用語かどうかはわかりませんが、つまり、ユーザーがプログラムをインストールするとき-初めてそれを実行するとき-開発者のマシンでプログラムをコンパイルするのではなく(特定のユーザーが使用するプラットフォームがわからない場合) -そして、プラットフォームごとに1つのインストーラーを配布したくありません)。
vemv 2011年

実行時に@vemvをコンパイルすると、VMは特定のハードウェア用のマシンインストラクションを特化できます
Lucina

回答:


8

Javaの場合、JVMはライブラリの境界を越える最適化を実行できます。たとえば、ライブラリのメソッドを独自のクライアントコードにインライン化できます。ライブラリは実行前に変更される可能性があるため、このタイプの最適化はコンパイル時には実行できませんでした。再コンパイルせずにlibfoo-1.0をlibfoo-1.1に置き換えることは完全に可能です。その場合、コンパイル時に行われるライブラリ間のインラインは完全に無効になります。

実行時にのみ最適化を実行することにより、ライブラリの変更により最適化が無効になる心配はありません。


1
インラインは、「Y.setX(x)」(Yは3番目のライブラリからのもの)を呼び出すマシンコードを生成する代わりに、「this.x = x」を実行して、「Yx = x 」

要約すると、ランタイムにはコンパイル時間にはない情報があります。
Daniel Gratzer 2013年

6

これにより、多くの機能を使用できなくなります。たとえば、JITは実行時にロードされたDLLから新しいジェネリックインスタンスをどのように生成できますか?これらのDLLはインストール時には存在しません。


1
答えを乾杯。私はインスタンス化の問題を理解していると思います-あなたの返事は少し簡潔すぎるので100%確実ではありません。また、利用できない他の機能をリストすることは、あなたのポイントをより強くするでしょう。
vemv 2011年

3
または一般的に、JITは入力に基づいて最適化を行うことができます。実行時にロードされるDLLは、入力の1つのタイプです。
amara 2011年

1
明らかに、これらのDLLのも同様に設置され、各DLLがでコンパイルすることができ、そのインストール時間。モジュール間の最適化は失われますが、これらはいずれにしても少し理論的なものです。
MSalters 2011年

@MSalters:すべてのDLLに「インストール」時間があるわけではありません。
DeadMG 2011年

@DeadMG:とにかく、架空のシステムについて取り組んでいます。このようなシステムでは、インストールが簡単に必要な場合があります。(さらに、実行可能コードの導入を明示的に管理することは、セキュリティ上の利点になります)。
MSalters

5

これは、少なくとも.NETアプリケーションでは可能です。ネイティブイメージジェネレーターを参照

管理対象アプリケーションのパフォーマンスを向上させるツール。Ngen.exeは、コンパイルされたプロセッサ固有のマシンコードを含むファイルであるネイティブイメージを作成し、ローカルコンピューターのネイティブイメージキャッシュにインストールします。ランタイムは、ジャストインタイム(JIT)コンパイラーを使用して元のアセンブリをコンパイルする代わりに、キャッシュからネイティブイメージを使用できます...


これは、Androidアプリのパフォーマンスを向上させるためにGoogleが作成したAndroidランタイム(ART)にも似ていることに注意してください
neelsg

3

説明に従って質問を言い換えると、次のようになります。

プログラムを初めて実行したときに、バイトコードをネイティブコードにコンパイルできないのはなぜですか。

次の問題が発生します。

  • 結果はどこに保存されますか?バイトコードを含むファイルが書き込み可能であるとは限りません。開発者がテストを実行するたびに新しい.exeを永続ストレージにダンプすることによって、開発者のマシンを膨らませたくありません。また、ファイルを一時ストレージに保存すると、次回の再起動時にファイルが失われるため、それほど多くは得られません。

  • 毎回わずかに遅いスタートアップを、非常に遅いスタートアップに交換します。クライアントに大きな印象を残さない。

  • 動的クラスローディングで重大な問題が発生します。


2
最初のポイントは簡単です。キャッシュは非常によく理解されています。基礎となる実行可能バイトコードが削除されると、関連するキャッシュエントリを削除できます。また、実行時間が長すぎない場合にも削除できます。2番目のポイントについては、バックグラウンドスレッドで未使用のメソッドのコンパイルを行うことができます。これは、呼び出されたメソッドをフォアグラウンドでコンパイルする起動時間を妨げないはずです。
MSalters、2011年

私が理解している限り、問題は最初の実行時のコンパイルではなく、インストール時のコンパイルです。
Nemanja Trifunovic 2011年

@NemanjaTrifunovic、質問のコメントを読んでください。
Peter Taylor

1
申し訳ありませんが、よく説明できなかったと思います。アプリケーションを初めて実行するときは、それ以上のコンパイルは必要ありません。Linuxで使用する前にCプログラムをコンパイルする必要がある場合と同様です。
vemv 2011年

1
私はそれがインストールとしてかなり数えられると思います-それらのコンパイル/ビルドプロセスはあなたのためにすでにスクリプトされています。
vemv
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.