CPythonのような他のランタイムと比較して、JVM(特に、Sunの実装)の実行が正確に遅くなる理由は何ですか?私の印象は、ライブラリが必要であるかどうかに関係なく、ロードされる大量のライブラリに主に関係しているというものでしたが、修正するのに10年はかかりません。
考えてみてください。JVMの開始時間はWindowsのCLRと比べてどうですか。 MonoのCLRはどうですか?
更新:私は、Unixで一般的である、チェーンされた小さなユーティリティの使用例に特に関心があります。 Javaこのスタイルに適していますか?起動時のオーバーヘッドJavaが発生した場合、Javaプロセスごとに合計されますか?または、オーバーヘッドは最初のプロセスでのみ実際に現れますか?
こちらが Wikipediaがこの問題について述べていること (参考文献あり)です。
ほとんどの場合、ディスクからデータ(クラス)をロードするだけで済みます(つまり、起動時間はI/Oバウンドです)。
いくつかの解決策に注意してください:
JVMの起動を高速化するメカニズムは2つあります。 1つ目は、クラスデータ共有メカニズムです。これは、Java 6 Update 21以降(HotSpot Client VMでのみ、および私の知る限り、シリアルガベージコレクタでのみ)からサポートされます)
これを有効にするには、-Xshareを設定する必要があります(一部の実装では:-Xshareclasses)JVMオプション。
この機能の詳細については、以下をご覧ください。 クラスデータの共有
2番目のメカニズムは、Javaクイックスターターです。OSの起動時にクラスをプリロードできます。詳細は Javaクイックスターター を参照してください。
簡単なJavaアプリを1.6(Java 6)クライアントJVMで実行すると、私のマシンでは瞬時に見えるようです。Sunは、クライアントJVMをチューニングして、より高速に起動しようとしました(クライアントJVMがデフォルトです)。したがって、追加のjarファイルが大量に必要ない場合は、起動を高速化する必要があります。
SunのHotSpot for x86_64(64ビットコンパイル済み)を使用している場合、現在の実装はサーバーモードでのみ機能することに注意してください。つまり、完全な最適化で読み込まれるすべてのクラスをプリコンパイルしますが、32ビットバージョンはクライアントモードをサポートします。そして、最もCPUを集中的に使用する部分のみを最適化しますが、起動時間が短縮されます。
たとえば、次を参照してください。
そうは言っても、少なくとも私のマシン(64ビットカーネルのLinux x86_64)では、32ビットHotSpotバージョンは(-clientおよび-serverフラグを介して)クライアントモードとサーバーモードの両方をサポートしますが、デフォルトはサーバーモードですが、64ビットバージョンはサーバーモード。
それは本当にあなたがスタートアップの間に何をしているかに依存します。 Hello Worldアプリケーションを実行すると、私のマシンで0.15秒かかります。
ただし、Javaはクライアントまたはサーバー/サービスとして実行するのに適しています。つまり、起動時間は接続時間(約0.025ミリ秒)または往復時間の応答ほど重要ではありません。時間(<< 0.001 ms)。
理由はいくつかあります。
jar
sが多いCLRについてはわかりませんが、次回のネイティブバージョンのアセンブリをキャッシュするため、多くの場合より高速です(したがって、JITする必要はありません)。 CPythonはインタープリターであり、IIRCはJITを実行しないため、起動が速くなります。
すでに述べたものに加えて(特に、圧縮されたJARからのクラスのロード); HotSpotが一般的に使用されるバイトコードをコンパイルする前にインタープリターモードで実行します。また、HotSpotコンパイルのオーバーヘッド、JDKクラス自体によって行われる初期化のかなりの部分もあります。多くの最適化は、起動速度が問題にならない、長時間実行されるシステムを優先して行われます。
また、UNIXスタイルのパイプライン処理については、JVMを何度も起動および再起動する必要はありません。それは効率的ではありません。むしろ、ツールのチェーンはJVM内で発生するはずです。これは、JVM内からそのようなツールを開始することを除いて、Java以外のUnixツールと簡単に混在させることはできません。
JavaまたはCLRなどのリッチタイプシステムを備えたすべてのVMは、CまたはC++に見られるようなそれほどリッチではないシステムと比較すると、瞬時ではありません。これは主に、 VM、多くのクラスが初期化され、実行中のシステムに必要です。初期化されたシステムのスナップショットは役立ちますが、そのイメージをメモリに再度ロードするなどのコストはかかります。
メインを持つ単純なhello worldスタイルの1つのライナークラスは、まだロードして初期化する必要があります。クラスを検証するには、多くの依存関係のチェックと検証が必要であり、すべての実行に時間と多くのCPU命令がかかります。一方、Cプログラムはこれらを実行せず、いくつかの命令を実行してから、プリンター関数を呼び出します。