Javaの性能のソースを表示
←
Javaの性能
ナビゲーションに移動
検索に移動
あなたには「このページの編集」を行う権限がありません。理由は以下の通りです:
この操作は、次のグループに属する利用者のみが実行できます:
登録利用者
。
このページのソースの閲覧やコピーができます。
'''Javaの性能'''(ジャバのせいのう)では、[[Javaプラットフォーム]]の性能について説明する。[[プログラミング言語]]としての[[Java]]に対する批判や、Javaプラットフォームの性能に対する批判は「[[Javaに対する批判]]」の記事を参照のこと。この記事ではJavaプラットフォームの性能について批判以外の説明をする。 プログラミング言語[[Java]]は、その「ネットワークから送り込まれるプログラムの安全な実行」や「[[write once, run anywhere]]」というスローガンを、業界にありがちなスローガンだけのスローガンではなく可能な限り達成するべく、[[Javaバイトコード]]にコンパイルするコンパイラと、Javaバイトコードを解釈実行するインタプリタである[[Java仮想マシン]] (Java VM, JVM)、という構成の実装を、公式の実装として伴って発表された。 [[コンピュータ科学]]的には特に目新しいものではない。しかし、従来の[[C言語]]あるいは[[C++]]といった[[ネイティブコード]]にコンパイルする言語で書かれた[[アプリケーションソフトウェア]]との性能比較や、当初はJVMのチューニングや高速化手法が進んでいなかったことによる性能の制限、また、当時の一般ユーザーが使っていた[[Microsoft Internet Explorer]]において、[[Javaアプレット]]が埋込まれたウェブページを表示しようとすると、JVMを起動するために数十秒から最悪の場合は数分も待たされたことから(起動してしまえば実は高性能なVMだったのだが)、「Javaは遅い」などと言われるようになったため、「Javaの性能」が議論されるようになった。 Javaプログラムの実行速度は[[実行時コンパイラ|JITコンパイル]]の導入(1997年 / 1998年の[[:en:Java version history|Java 1.1]]以降)や <ref>{{cite web | url=http://www.symantec.com/about/news/release/article.jsp?prid=19970407_03 | title=Symantec's Just-In-Time Java Compiler To Be Integrated Into Sun JDK 1.1| accessdate=2009-07-04}} </ref><ref>{{cite web | url=http://findarticles.com/p/articles/mi_hb6676/is_/ai_n26150624 | title=Apple Licenses Symantec's Just In Time (JIT) Compiler To Accelerate Mac OS Runtime For Java| accessdate=2009-07-04}} </ref> <!-- <ref>{{cite web | url=http://www.infoworld.com/cgi-bin/displayStory.pl?980416.ehjdk.htm | accessdate=2009-07-04 | title=Java gets four times faster with new Symantec just-in-time compiler}}</ref> -->、 コードの解析の機能が言語に追加されたこと、[[Java仮想マシン]]自体の最適化(2000年から[[サン・マイクロシステムズ]]のVMで標準的に動作するようになった[[HotSpot]]技術など)によって大きく向上した。 == 仮想マシンの最適化手法 == [[オラクル (企業)|オラクル]](旧[[サン・マイクロシステムズ]])のJVMの性能は徐々に向上してきたが、このJVMはいくつかの最適化を実装した最初の[[仮想機械]]であることも多く、そうした技術は類似のプラットフォームでも使用されている。 === ジャストインタイムコンパイル === {{See|実行時コンパイラ|HotSpot}} 初期の[[Java仮想マシン]]は[[Javaバイトコード|バイトコード]]のインタプリタであり、このことが性能に対する大きな足かせ(平均的なアプリケーションで、Java対Cで10〜20倍程度)になっていた<ref>[http://www.shudo.net/jit/perf/ Performance Comparison of Java/.NET Runtimes (Oct 2004)]</ref>。 Java 1.1で JIT コンパイラが導入された。 Java 1.2で[[HotSpot]]と呼ばれる技術が導入された。これは、[[Java仮想マシン]]がプログラムの頻繁に実行される箇所、「ホットスポット」の性能解析を実行中に実行し続けるもので、解析した情報は[[最適化 (情報工学)|最適化]]に利用して、他のパフォーマンスに影響のないコードには余分な負荷をかけることなく、性能を向上させることができる。 Java 1.3で[[HotSpot]]が標準で用いられるようになった。 HotSpot技術により、コードはまずインタプリタ実行され、「ホットスポット」が動的にコンパイルされる。Javaの性能測定においてベンチマークをとる前にプログラムを数回実行させる必要があるのはこのためである。 HotSpotによるコンパイルでは[[インライン展開]]、[[ループ展開]]、[[:en:Bounds-checking elimination|境界チェックの省略]]、アーキテクチャ固有の[[レジスタ割り付け]]などの様々な最適化手法が用いられる<ref>{{cite web | url=http://weblogs.java.net/blog/kohsuke/archive/2008/03/deep_dive_into.html | title=Deep dive into assembly code from Java | last=Kawaguchi|first=Kohsuke | date=2008-03-30 | accessdate=2008-04-02}} </ref>。 ベンチマークによってはこうした手法により10倍の性能向上が見られる<ref>[http://www.shudo.net/jit/perf/ この記事] によれば、インタプリタモードとHotspotで10倍以上性能が向上している。</ref>。 === 適応的最適化 === {{see|適応的最適化}} 適応的最適化 ([[:en:Adaptive optimization|adaptive optimization]]) とは、計算機科学においてプログラムの一部を現在の実行結果のプロファイルに基づき[[動的再コンパイル]] ([[:en:Dynamic recompilation|dynamic recompilation]]) する技術である。単純な実装では、適応的最適化はジャストインコンパイルとインタプリタ実行を選択するだけだが、より高水準のものでは、データの局所的な状態を用いて分岐を取り除き、インライン展開してコンテキスト切り替えを削減することもできる。 [[HotSpot]]のような[[Java仮想マシン]]は、一度[[実行時コンパイラ|JITコンパイル]]されたコードを解消 ([[:en:Deoptimization|deoptimization]]: 脱最適化) することも可能である。これによって、積極的な(場合によっては危険な)最適化を実行し、後で最適化を解消し安全な実行方法に戻ることもできる<ref>{{cite web | url=http://java.sun.com/products/hotspot/docs/whitepaper/Java_Hotspot_v1.4.1/Java_HSpot_WP_v1.4.1_1002_4.html#hotspot | title=The Java HotSpot Virtual Machine, v1.4.1 | publisher=[[サン・マイクロシステムズ]] | accessdate=2008-04-20}} </ref><ref>{{cite web | url=https://headius.blogspot.com/2008/01/langnet-2008-day-1-thoughts.html | title=Lang.NET 2008: Day 1 Thoughts | quote=''Deoptimization is very exciting when dealing with performance concerns, since it means you can make much more aggressive optimizations...knowing you'll be able to fall back on a tried and true safe path later on'' | last=Nutter|first=Charles | date=2008-01-28 | accessdate=2008-04-20}}</ref>。 === ガベージコレクション === {{see|ガベージコレクション}} Java 1.0と1.1の[[Java仮想マシン]]では、ガベージコレクション実行後の[[ヒープ領域|ヒープ]]が断片化する可能性のある[[マーク・アンド・スイープ]]方式の[[ガベージコレクション]]を採用していた。 Java 1.2より、Java仮想マシンは[[世代別ガベージコレクション]]を用いるようになり<ref>[https://www.ibm.com/developerworks/jp/java/library/j-jtp11253/index.html Javaの理論と実践: 1.4.1 JVM中のガーベジ・コレクション]</ref>、断片化が起こりづらくなった<ref>[https://www.ibm.com/developerworks/jp/java/library/j-jtp01274/index.html Javaの理論と実践: ガベージコレクションとパフォーマンス]</ref>。 現代的なJava仮想マシンは、[[ガベージコレクション]]の性能を改善する様々な手法を用いている<ref>例えば、停止時間が大幅に短くなっている。Java で書かれた[[:en:Quake II|Quake 2]]の例を参照[http://bytonic.de/html/jake2.html Jake2]</ref>。 === その他の最適化技術 === ==== バイトコード検証の分割 ==== [[クラス (コンピュータ)|クラス]]の実行に先立ち、[[オラクル (企業)|オラクル]]のJVMは[[バイトコード]]の検証を行う。バイトコードのロードと検証は特定のクラスがロードされ実行する準備ができた場合のみ行われ、プログラムの開始時点で行われるわけではない<ref>オラクル以外のJVM、たとえば [[IBM]] [[System i]]用のJava/400のように、検証の作業の大半を前もって行い、クラスを検証した情報をキャッシュしておくものもある。</ref>。しかし、Javaの[[Javaプラットフォーム#クラスライブラリ|クラスライブラリ]]も正規のJavaクラスであり、使用時にロードされるため、Javaプログラムの起動時間は例えば[[C++]]のプログラムより長くなることが多い。 ''分割検証''と呼ばれる技術がJavaプラットフォームの[[Java Platform, Micro Edition|J2ME]]で導入され、[[:en:Java version history|Java version 6]]から[[Java仮想マシン]]で利用されるようになった。これは[[バイトコード]]の検証を二つのフェーズに分割する<ref>[https://jdk.dev.java.net/verifier.html New Java SE 6 Feature: Type Checking Verifier] at java.net</ref>。 * 設計時 - ソースコードからバイトコードにクラスをコンパイルする際 * 実行時 - クラスをロードする際 こうした手法は、Javaコンパイラがクラスのコードの流れを解析し、コンパイルされたメソッドのバイトコードにクラスのフロー情報の概要を注釈(アノテート)することで動作する。実行時の検証を劇的に単純化するわけではないが、若干の処理を省略することができる。 ==== エスケープ解析と粗粒度ロック ==== {{see|ロック_(情報工学)|エスケープ解析}} Javaは言語レベルで[[スレッド (コンピュータ)|マルチスレッド]]に対応している。マルチスレッドとは、下記のようなことを可能にする技術である。 * [[並行コンピューティング]] - 例えばプログラムがバックグラウンドでタスクを実行中であってもユーザーがGUIを操作できるようにすることで、'''応答性'''や'''ユーザーに与える印象'''を改善する * [[並列コンピューティング]] - 例えば[[マルチコア]]プロセッサのアーキテクチャを活かして、依存関係のない複数の作業を異なるコアで同時に実行し、'''処理時間'''を削減する しかし、マルチスレッドを使用するプログラムは、スレッド間で共有される[[オブジェクト (プログラミング)|オブジェクト]]や[[メソッド (計算機科学)|メソッド]]、[[ブロック (プログラミング)|コードブロック]]に開発者が特別な注意を払う必要がある。またオブジェクトやコードブロックをロックすることは、それに伴うOSの性質によって時間のかかる操作である([[並行性制御]]や[[ロック (情報工学)|ロックの粒度]]を参照)。 Javaライブラリにはどのメソッドが複数のスレッドから使用されるか分からないため、マルチスレッド環境で使用される標準的なライブラリは常に[[ブロック (プログラミング)|コードブロック]]のロックを行っている。 Java 6以前では、複数の異なるスレッドが同時にオブジェクトを変更するリスクがない場合でも、仮想マシンはオブジェクトやコードブロックのロックをプログラムの要求にしたがって行っていた([[ロック (情報工学)|ロックの実装]]を参照)。例えば、ローカル変数の{{Javadoc:SE|java/util|Vector}}があり、それに対する ''add'' 操作を行う際、それが確実にローカルでしか使用されずロックが不要である状況でも、同時に他のスレッドから変更されないようロックを行っていた。 <syntaxhighlight lang="java"> public String getNames() { Vector v = new Vector(); v.add("Me"); v.add("You"); v.add("Her"); return v.toString(); } </syntaxhighlight> Java 6では、コードブロックやロックは必要なときだけロックされるようになり[http://www-128.ibm.com/developerworks/java/library/j-jtp10185/] [http://blogs.sun.com/dagastine/entry/java_synchronization_optimizations_in_mustang]、上記の例では仮想マシンは<code>Vector</code>オブジェクトのロックを行わない。 バージョン 6 Update 14で、Javaは実験的ながら[[エスケープ解析]]をサポートするようになった[http://java.dzone.com/articles/escape-analysis-java-6-update]。 ==== レジスタ割付の改善 ==== [[:en:Java version history|Java 6]]以前では、「クライアント」仮想マシンにおける[[レジスタ割り付け]]はかなり初歩的なもので([[ブロック (プログラミング)|ブロック]]を超えてレジスタが生存できない)、これは例えば[[x86]]のような[[レジスタ (コンピュータ)|レジスタ]]が少ない[[CPU設計|アーキテクチャ]]で問題となる。ある操作に必要なレジスタが足りなくなると、コンパイラはレジスタからメモリ(ないしはメモリからレジスタ)に値をコピーするが、メモリは通常レジスタより低速なので、通常より時間がかかる。なお「サーバ」仮想マシンでは[[グラフ彩色]]によるレジスタ割り付けを行うため、こうした問題は生じない。 レジスタ割り付けの最適化はサンのJDK 6で導入された<ref>[http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6320351 Bug report: new register allocator, fixed in Mustang (JDK 6) b59]</ref>。これは同じレジスタを、可能な場合コードブロックをまたがって使用することでメモリアクセスを減らすもので、報告によればいくつかのベンチマークで約60%の性能向上が得られた<ref>[http://weblogs.java.net/blog/opinali/archive/2005/11/mustangs_hotspo_1.html Mustang's HotSpot Client gets 58% faster!] in Osvaldo Pinali Doederlein's Blog at java.net</ref>。 ==== クラスデータの共有 ==== オラクルJVMにおけるクラスデータの共有 (class data sharing: CDS) とは、Javaアプリケーションの起動時間を短くし、同時に[[:en:Memory-footprint|メモリ使用量]]を削減する仕組みである。[[Java仮想マシン|JRE]]がインストールされると、インストーラーはシステム[[JAR (ファイルフォーマット)|JARファイル]](Java のクラスライブラリを全て含むJARファイルで、rt.jarと呼ばれる)からいくつかのクラスを特別な内部表現形式でロードし、この内部表現を「共有書庫」ファイルとして書き出す。それ以降の[[Java仮想マシン|JVM]]の呼び出し時には、共有書庫ファイルは[[メモリマップトファイル|メモリマッピング]]され、これによってクラスをロードする時間を短縮し、複数 JVM プロセスがこれらのクラスのメタデータを共有できるようになる<ref>[http://java.sun.com/j2se/1.5.0/docs/guide/vm/class-data-sharing.html Class Data Sharing] at java.sun.com</ref>。 起動時間の短縮は、特に小さなプログラムで効果が著しい<ref>[http://www.artima.com/forums/flat.jsp?forum=121&thread=56613 Class Data Sharing in JDK 1.5.0] in Java Buzz Forum at [http://www.artima.com/ artima developer]</ref>。 == Sun の Java バージョンによる性能の向上 == {{see|:en:Java version history}} 上記以外にも、オラクルのJavaは各バージョンでJava APIの性能向上を多数盛り込んでいる。 === JDK 1.1.6 === 仮想マシンレベルの向上: * 最初の[[実行時コンパイラ|JITコンパイル]]([[シマンテック]]のJITコンパイラによる)<ref>{{cite web | url=http://www.symantec.com/about/news/release/article.jsp?prid=19970407_03 | title=Symantec's Just-In-Time Java Compiler To Be Integrated Into Sun JDK 1.1 | accessdate=2009-07-04}} </ref><ref>{{cite web | url=http://www.infoworld.com/cgi-bin/displayStory.pl?980416.ehjdk.htm | title=Java gets four times faster with new Symantec just-in-time compiler | accessdate=2009-07-04 }} </ref> === J2SE 1.2 === 仮想マシンレベルの向上: * [[#世代別ガベージコレクション|世代別ガベージコレクション]] === J2SE 1.3 === 仮想マシンレベルの向上: * [[HotSpot]]技術による[[実行時コンパイラ|JITコンパイル]] === J2SE 1.4 === サン・マイクロシステムズが1.3から1.4での性能向上をまとめた[http://java.sun.com/j2se/1.4.2/performance.guide.html リンク]を参照 === Java SE 5.0 === 仮想マシンレベルの向上: * [[#クラスデータの共有|クラスデータの共有]][http://java.sun.com/performance/reference/whitepapers/5.0_performance.html リンク]参照。Sun がバージョン 1.4 から 5.0 での性能向上をまとめている。 === Java SE 6 === 仮想マシンレベルの向上: * [[#バイトコード検証の分割|バイトコード検証の分割]] * [[#エスケープ解析と粗粒度ロック|エスケープ解析と粗粒度ロック]] * [[#レジスタ割付の改善|レジスタ割付の改善]] その他の向上: * [[Java OpenGL]]および[[Java 2D]]パイプラインの性能向上<ref>[http://weblogs.java.net/blog/campbell/archive/2005/07/strcrazier_perf.html STR-Crazier: Performance Improvements in Mustang] in Chris Campbell's Blog at java.net{{リンク切れ|date=2019-09}}</ref> * [[Java 2D]]の性能はJava 6で大きく向上した。<ref>See [http://jroller.com/page/dgilbert?entry=is_java_se_1_6 here] for a benchmark showing an approximately 60% performance boost from Java 5.0 to 6 for the application [http://www.jfree.org JFreeChart]</ref> === Java SE 6 Update 10 === * Java Quick Starterにより、OS起動時にJRE のデータをディスクキャッシュにロードしておくことでアプリケーションの起動時間を短縮する<ref name="jrecache">{{cite web | url=http://java.sun.com/developer/technicalArticles/javase/consumerjre#Quickstarter | title=Consumer JRE: Leaner, Meaner Java Technology | publisher=サン・マイクロシステムズ |last=Haase|first=Chet | quote=''At the OS level, all of these megabytes have to be read from disk, which is a very slow operation. Actually, it's the seek time of the disk that's the killer; reading large files sequentially is relatively fast, but seeking the bits that we actually need is not. So even though we only need a small fraction of the data in these large files for any particular application, the fact that we're seeking all over within the files means that there is plenty of disk activity. '' | date=May 2007 | accessdate=2007-07-27}} </ref>。 * プラットフォームの一部で、アプリケーションを実行する際に必要な部分もWebからダウンロードされるようになった。JRE全体のサイズは12MBになり、典型的なSwingアプリケーションは4MBしか使用しない。残りはバックグラウンドでダウンロードされる<ref>{{cite web | url=http://java.sun.com/developer/technicalArticles/javase/consumerjre#JavaKernel | title=Consumer JRE: Leaner, Meaner Java Technology | publisher=サン・マイクロシステムズ | last=Haase|first=Chet | date=May 2007 | accessdate=2007-07-27}} </ref>。 * [[Direct3D]]が標準で使用されるようになり、[[Microsoft Windows|Windows]]上でのグラフィック性能が向上した<ref>{{cite web | url=http://java.sun.com/developer/technicalArticles/javase/consumerjre#Performance | title=Consumer JRE: Leaner, Meaner Java Technology | publisher=サン・マイクロシステムズ | last=Haase|first=Chet | date=May 2007 | accessdate=2007-07-27}} </ref>。複雑な[[Java 2D]]の操作を高速化するため[[Graphics Processing Unit|GPU]]の[[シェーダー]]を使用するようになった<ref>{{cite web | url=http://weblogs.java.net/blog/campbell/archive/2007/04/faster_java_2d.html | title=Faster Java 2D Via Shaders | last=Campbell|first=Chris | date=2007-04-07 | accessdate=2008-04-26}} </ref>。 === 今後の性能改善点 === 今後の性能改善は、Java 6のupdateかJava 7で計画されている<ref>{{cite web | url=http://java.sun.com/developer/technicalArticles/javase/consumerjre | title=Consumer JRE: Leaner, Meaner Java Technology | publisher=サン・マイクロシステムズ |last=Haase|first=Chet | date=May 2007 | accessdate=2007-07-27}} </ref>。 * [[Java仮想マシン|JVM]]での[[動的プログラミング言語]]のサポート。[[:en:Da Vinci Machine|Multi Language Virtual Machine]]のプロトタイプ開発に基づく<ref>{{cite web | url=http://www.jcp.org/en/jsr/detail?id=292 | title=JSR 292: Supporting Dynamically Typed Languages on the Java Platform | publisher=jcp.org | accessdate=2008-05-28}} </ref>。 * 並列性を提供するライブラリの改善。[[マルチコア]]プロセッサ上での[[並列コンピューティング|並列処理]]を行う<ref>{{cite web | url=http://www.ibm.com/developerworks/java/library/j-jtp03048.html?ca | title=Java theory and practice: Stick a fork in it, Part 2 | last=Goetz|first=Brian | date=2008-03-04 | accessdate=2008-03-09}} </ref><ref>{{cite web | url=http://www.infoq.com/news/2008/03/fork_join | title=Parallelism with Fork/Join in Java 7 | last=Lorimer|first=R.J. | publisher=infoq.com | date=2008-03-21 | accessdate=2008-05-28}} </ref> * ''多段コンパイル''と呼ばれる手法で、[[Java仮想マシン]]が'''クライアント'''と'''サーバ'''という二種類の[[実行時コンパイラ|JITコンパイル]]の両方を、同じセッションで使用できるようにする<ref>{{cite web | url=http://developers.sun.com/learning/javaoneonline/2006/coreplatform/TS-3412.pdf | title=New Compiler Optimizations in the Java HotSpot Virtual Machine | publisher=サン・マイクロシステムズ | date=May 2006 | accessdate=2008-05-30}} </ref>。 ** '''クライアント'''のJITコンパイルは、起動時に使用される(起動時と小規模なアプリケーションに適しているため) ** '''サーバー'''のJITコンパイルは、長時間動作するアプリケーションに使用される('''クライアント'''より性能がよいため) * 既存の並列化されたガベージコレクタ (CMS collector; Concurrent Mark-Sweep collector) を、停止時間が一定であることを保証した新しい G1 (Garbage First) コレクタに置き換える<ref>{{cite web | url=http://www.infoq.com/news/2008/05/g1 | title=JavaOne: Garbage First | publisher=infoq.com | last=Humble|first=Charles | date=2008-05-13 | accessdate=2008-09-07}} </ref><ref>{{cite web | url=http://blogs.sun.com/theplanetarium/entry/java_vm_trying_a_new | title=Java VM: Trying a new Garbage Collector for JDK 7 | last=Coward|first=Dany | date=2008-11-12 | accessdate=2008-11-15}} </ref>。 == 他の言語との比較 == Javaプログラムは通常[[仮想機械|仮想マシン]]によって実行時に[[実行時コンパイラ|JITコンパイル]]されるが、 C/C++のように[[事前コンパイラ|事前コンパイル]]することも可能である。JITコンパイルされた場合、その性能は一般的に[http://shootout.alioth.debian.org/debian/benchmark.php?test=all&lang=all] * [[C言語|C]]や[[C++]]などのコンパイル言語と比べて性能は劣る。ただ通常のタスクでは大きな性能の低下はない。 * [[C Sharp|C#]]などの他のJITコンパイルを行う言語と同様の性能を示す。 * 性能の良いネイティブコードへのコンパイラ([[実行時コンパイラ|JIT]]あるいは[[事前コンパイラ|AOT]])を持たない[[Perl]]、[[Ruby]]、[[PHP (プログラミング言語)|PHP]]、[[Python]]などの言語より、大幅に高い性能を示す<ref>Python には[[Psyco]]があるが、扱えるコードが限定されており、また Psyco を利用しても Java より性能が低い([http://shootout.alioth.debian.org/gp4sandbox/benchmark.php?test=all&lang=all リンク]参照)。</ref>。 === プログラムの速度 === Javaプログラムの平均的な性能は徐々に向上しており、Javaの性能は[[C言語|C]]や[[C++]]に匹敵するほどになっており、Javaが低速な場合もあるが、高速な場合もある<ref name="idiom">{{cite web|url=http://scribblethink.org/Computer/javaCbenchmark.html |title=Performance of Java versus C++ |publisher=Computer Graphics and Immersive Technology Lab, University of Southern California| author=Lewis, J.P. |coauthors=Neumann, Ulrich|accessdate=2009-07-04}} </ref>。2009年3月の時点で、Java は [http://shootout.alioth.debian.org/ Computer Language Benchmarks Game]においてC/C++より5-15%遅い。ベンチマークは小規模で数値演算中心の性能を測定するとも言われる。これは、おそらくCに有利に働く。実際のプログラムでは、JavaがCを上回ったり性能の差はなかったりする。例として、[[:en:Jake2|Jake2]]([[:en:Quake II|Quake 2]]クローンで、[[GNU General Public License|GPL]]のCコードをJavaに変換して作成)のベンチマークがあり、Java 5.0のバージョンは、同じハードウェア構成でCの性能を上回る<ref>: 260/250 [[フレームレート|FPS]]対245 FPS([http://www.bytonic.de/html/benchmarks.html ベンチマーク結果]参照)</ref>。データがどのように計測されたか明確ではないが(例えば、オリジナルのQuack 2の実行ファイルが1997年にコンパイルされたものであれば、現在のコンパイラではよりよい最適化を行うことができる)、Javaの同じソースコードがVMを更新するだけで大きく性能向上しており、これは100%静的にコンパイルする方法では達成できない。 また、Javaや類似の言語では可能な最適化で、C/C++では実施できないものもある<ref name="idiom"/>。 * C形式の[[ポインタ (プログラミング)|ポインタ]]は、ポインタをサポートする言語での最適化を困難にする。 * コードがプログラムの実行前にコンパイルされるため、[[#適応的コンパイル]]は完全にコンパイルされたコードでは実施できず、アーキテクチャの機能や、コードパスを用いた最適化の恩恵を受けられない。いくつかのベンチマークの結果は、C/C++の性能はプロセッサアーキテクチャに対応したコンパイルオプション(たとえば[[ストリーミングSIMD拡張命令#SSE2|SSE2]]の利用など)に強く依存しており、Javaプログラムは[[実行時コンパイラ|JITコンパイル]]により対象のアーキテクチャに適応できることを示している<ref>{{cite web | url=http://shootout.alioth.debian.org/gp4/benchmark.php?test=mandelbrot&lang=all#about | title=mandelbrot benchmark | publisher=Computer Language Benchmarks Game | accessdate=2008-02-16}} </ref>。 * [[#エスケープ解析および粗粒度ロック|エスケープ解析]]の手法は、[[オブジェクト (プログラミング)|オブジェクト]]がどこで使用されるかをコンパイラが知ることができないため、たとえば[[C++]]では使用できない(また、ポインタの使用が原因でもある)。 しかし、JavaとC/C++での[[ベンチマーク]]による比較は実施する作業に大きく依存する。例えば、Java 5.0と比較すると、 * 32 / 64ビットの数値演算<ref>{{cite web | url=http://www.ddj.com/java/184401976?pgno=2 | title=Microbenchmarking C++, C#, and Java: 32-bit integer arithmetic | publisher=[[Dr. Dobb's Journal]] | date=2005-07-01 | accessdate=2007-11-17}} </ref><ref>{{cite web | url=http://www.ddj.com/java/184401976?pgno=12 | title=Microbenchmarking C++, C#, and Java: 64-bit double arithmetic | publisher=[[Dr. Dobb's Journal]] | date=2005-07-01 | accessdate=2007-11-17}} </ref>、ファイル[[入出力]]<ref>{{cite web | url=http://www.ddj.com/java/184401976?pgno=15 | title=Microbenchmarking C++, C#, and Java: File I/O | publisher=[[Dr. Dobb's Journal]] | date=2005-07-01 | accessdate=2007-11-17}} </ref>、[[例外処理]]<ref>{{cite web | url=http://www.ddj.com/java/184401976?pgno=17 | title=Microbenchmarking C++, C#, and Java: Exception | publisher=[[Dr. Dobb's Journal]] | date=2005-07-01 | accessdate=2007-11-17}} </ref> ではC/C++と同等の性能を示す。 * [[:en:Collection (computing)|コレクション]]<ref>{{cite web | url=http://www.ddj.com/java/184401976?pgno=18 | title=Microbenchmarking C++, C#, and Java: Single Hash Map | publisher=[[Dr. Dobb's Journal]] | date=2005-07-01 | accessdate=2007-11-17}} </ref><ref>{{cite web | url=http://www.ddj.com/java/184401976?pgno=19 | title=Microbenchmarking C++, C#, and Java: Multiple Hash Map | publisher=[[Dr. Dobb's Journal]] | date=2005-07-01 | accessdate=2007-11-17}} </ref>、[[オブジェクト (プログラミング)|オブジェクト]]の生成、解放、メソッド呼び出しの性能<ref>{{cite web | url=http://www.ddj.com/java/184401976?pgno=9 | title=Microbenchmarking C++, C#, and Java: Object creation/ destruction and method call | publisher=[[Dr. Dobb's Journal]] | date=2005-07-01 | accessdate=2007-11-17}} </ref> では、Javaの方がC++より性能が高い。 * [[配列]]<ref>{{cite web | url=http://www.ddj.com/java/184401976?pgno=19 | title=Microbenchmarking C++, C#, and Java: Array | publisher=[[Dr. Dobb's Journal]] | date=2005-07-01 | accessdate=2007-11-17}} </ref> の操作はC/C++の方が高速である。 * [[三角関数]] の性能はC/C++の方が高い<ref>{{cite web | url=http://www.ddj.com/java/184401976?pgno=19 | title=Microbenchmarking C++, C#, and Java: Trigonometric functions | publisher=[[Dr. Dobb's Journal]] | date=2005-07-01 | accessdate=2007-11-17}} </ref>。 === 起動時間 === Javaアプリケーションの起動時は、膨大な数のクラス([[Javaプラットフォーム#クラスライブリ|プラットフォームのクラスライブラリ]]の{{要出典範囲|date=2019-11|全て}}のクラスを含む)を使用前にロードしなければならないため、[[C言語|C]]や[[C++]]よりもかなり時間がかかることが多い。 起動時間の大半はJVMの初期化やクラスのロードそのものではなく、I/Oを伴う操作によるものと{{独自研究範囲|date=2019-09|思われる}} (''rt.jar''のクラスデータファイルは40MBあり、JVMは多数のデータをこの巨大なファイルをシークして取り出さなければならない)<ref name="jrecache" />。いくつかの実験により、[[#バイトコード検証の分割|バイトコード検証分割]]の方法を用いるとクラスのロードは約40%向上するが、大規模なプログラムの起動時間は5%しか向上しないことがわかった<ref>{{cite web | url=http://forums.java.net/jive/thread.jspa?messageID=94530 | title=How fast is the new verifier? | date=2006-02-07 | accessdate=2007-05-09}}</ref>。 改善幅は小さいものの、単純な操作を実行しすぐ終了するような小さなプログラムでは、Javaプラットフォームのデータローディングはプログラムの操作の数倍の負荷であるため、向上が目に見えやすい。 Java SE 6 Update 10より、オラクルのJREにはQuick Starterが同梱されるようになり、OSの起動時にクラスのデータをロードしておくことで、ディスクではなくディスクキャッシュからデータを読み出すことができるようになる。 [[:en:Excelsior JET|Excelsior JET]]では、この問題に対して別の方向からアプローチしている。JETのStartup Optimizerはアプリケーションの起動時にディスクから読み出すデータを削減し、さらにシーケンシャルに読み出せるよう配置する。 === メモリ使用量 === Javaのメモリ使用量はC/C++より大きい。 * 32ビット環境のJavaでは各オブジェクトに最低8バイト、各配列に12バイトのオーバーヘッドが存在する(64ビットの環境では倍)。また、オブジェクトのサイズが8の倍数でない場合は、8の倍数に切り上げられる。そのため、4バイトの整数を格納するオブジェクトは32ビット環境で16バイト消費する。ただし、C++も[[仮想関数テーブル]]を持つ型は、各オブジェクトに32ビット環境で4バイト、64ビット環境で8バイトの[[ポインタ (プログラミング)|ポインタ]]を余分に割り当てる[http://www.informit.com/guides/content.aspx?g=cplusplus&seqNum=195]。また、[[多重継承]]や[[仮想継承]]をするとメンバー[[関数ポインタ]]のサイズが増大する処理系もある<ref>[[Microsoft Visual C++]]など。</ref>。 * [[Javaプラットフォーム#クラスライブリ|クラスライブラリ]]が(最低でもプログラムが使用する分は)実行前にロードされていなければならない[http://www.tommti-systems.de/go.html?http://www.tommti-systems.de/main-Dateien/reviews/languages/benchmarks.html]。 * Javaのバイナリと、ネイティブにJITコンパイルしたものの両方がメモリ上に存在する。 * 仮想マシン自体がメモリを消費する。 === 三角関数 === Javaの三角関数の性能は、Cと比べて悪い。Javaが数値演算の結果に(使用するハードウェアとも合致しない場合もある)厳密な仕様を定義している<ref>{{cite web|url = http://java.sun.com/javase/6/docs/api/java/lang/Math.html |title = Math (Java Platform SE 6) |publisher = [[サン・マイクロシステムズ]] |accessdate=2008-06-08}}</ref>ためである。 [[Intel 8087|x87]]での絶対値<math>\pi</math>/4以上の値に対するサイン、コサインの演算結果は、<math>\pi</math>の値に近似値を用いるため正確ではない<ref>{{cite web|url=http://blogs.sun.com/jag/entry/transcendental_meditation |title = Transcendental Meditation |accessdate=2008-06-08| date=2005-07-27 |first=James |last=Gosling |authorlink=James Gosling}} </ref>。JVMの実装ではソフトウェアで正確な演算を行わなければならず、その領域では大きな性能低下を引き起こす<ref>{{cite web|url=http://www.osnews.com/story/5602&page=3 |title=Nine Language Performance Round-up: Benchmarking Math & File I/O |last=W. Cowell-Shah |first=Christopher |date=2004-01-08 |accessdate=2008-06-08}} </ref>。 === Java Native Interface === [[Java Native Interface]]はオーバーヘッドが大きく、JVM上で動作するコードとネイティブコードの境界を行き来するコストが高くなっている<ref>{{cite web | url=http://java.sun.com/docs/books/performance/1st_edition/html/JPNativeCode.fm.html | title=JavaTM Platform Performance: Using Native Code | last=Wilson|first=Steve | coauthors=Jeff Kesselman | publisher=[[サン・マイクロシステムズ]] | date=2001 | accessdate=2008-02-15}} </ref><ref>{{cite web | url=http://janet-project.sourceforge.net/papers/jnibench.pdf | title=Efficient Cooperation between Java and Native Codes - JNI Performance Benchmark | last=Kurzyniec |first=Dawid | coauthors=Vaidy Sunderam | accessdate=2008-02-15}} </ref>。 === ユーザインタフェース === [[Swing]]は[[ウィジェット (GUI)|ウィジェット]]の描画をPure Javaで記述された[[Java 2D]] [[アプリケーションプログラミングインタフェース|API]]に任せているため、ネイティブの[[ウィジェット・ツールキット]]と比較して低速であるとされてきた。しかし、SwingとOSのネイティブGUIライブラリに描画処理を任せる[[Standard Widget Toolkit]]をベンチマークで比較しても、片方が明確に速いわけではなく、結果はコンテキストや環境に大きく依存した<ref>{{cite web | url=http://cosylib.cosylab.com/pub/CSS/DOC-SWT_Vs._Swing_Performance_Comparison.pdf | title=SWT Vs. Swing Performance Comparison | quote=''Initial expectation before performing this benchmark was to find SWT outperform Swing. This expectation stemmed from greater responsiveness of SWT-based Java applications (e.g., Eclipse IDE) compared to Swing-based applications. However, this expectation could not be quantitatively confirmed.'' | first=Kri?nar|last=Igor | publisher=cosylab.com | date=2005-05-10 | accessdate=2008-05-24}} </ref>。 === 高性能計算分野での Java の使用 === いくつかの独立した研究によれば、[[高性能計算]] (HPC) における Javaの性能は、演算中心のベンチマークで[[FORTRAN]]と同等であるが、JVMは[[グリッド・コンピューティング|グリッドネットワーク]]上の通信が多くなると、スケーラビリティに問題があるようである<ref>{{cite web | url=http://hal.inria.fr/inria-00312039/en | title=Current State of Java for HPC | quote=''We first perform some micro benchmarks for various JVMs, showing the overall good performance for basic arithmetic operations(...). Comparing this implementation with a Fortran/MPI one, we show that they have similar performance on computation intensive benchmarks, but still have scalability issues when performing intensive communications.'' | author=Brian Amedro, Vladimir Bodnartchouk, Denis Caromel, Christian Delbe, Fabrice Huet, Guillermo L. Taboada | publisher=[[INRIA]] | date=August 2008 | accessdate=2008-09-04}} </ref>。 しかし、Javaで記述された[[高性能計算]]のアプリケーションがベンチマークで最高の成績を出したことがある。[[2008年]]、Javaで記述されたHPCのプロジェクト Apache [[Hadoop]] が、テラバイト級の整数のソートで最高速の結果を出した<ref>{{cite web | url=http://developer.yahoo.net/blogs/hadoop/2008/07/apache_hadoop_wins_terabyte_sort_benchmark.html | title=Apache Hadoop Wins Terabyte Sort Benchmark | quote=''This is the first time that either a Java or an open source program has won.'' | author=Owen O'Malley - Yahoo! Grid Computing Team | date=July 2008 | accessdate=2008-12-21}} </ref>。 == 脚注 == {{reflist|2}} == 関連項目 == * [[Javaプラットフォーム]] * [[Java仮想マシン]] * [[Javaバイトコード]] * [[HotSpot]] * [[Java仮想マシン|Java Runtime Environment]] * [[:en:Java version history]] * [[仮想機械]] * [[共通言語ランタイム]] * [[コンパイラ最適化]] * [[性能解析]] == 外部リンク == * [https://javaperformancetuning.com/ Java Performance Tuning] * [https://prefetch.net/presentations/DebuggingJavaPerformance.pdf Debugging Java performance problems] * [https://www.oracle.com/java/technologies/ Java Technical] {{Java}} {{DEFAULTSORT:Javaのせいのう}} [[Category:Javaプラットフォーム]] [[Category:ソフトウェア最適化]]
このページで使用されているテンプレート:
テンプレート:Cite web
(
ソースを閲覧
)
テンプレート:Java
(
ソースを閲覧
)
テンプレート:Javadoc:SE
(
ソースを閲覧
)
テンプレート:Reflist
(
ソースを閲覧
)
テンプレート:See
(
ソースを閲覧
)
テンプレート:リンク切れ
(
ソースを閲覧
)
テンプレート:独自研究範囲
(
ソースを閲覧
)
テンプレート:要出典範囲
(
ソースを閲覧
)
Javaの性能
に戻る。
ナビゲーション メニュー
個人用ツール
ログイン
名前空間
ページ
議論
日本語
表示
閲覧
ソースを閲覧
履歴表示
その他
検索
案内
メインページ
最近の更新
おまかせ表示
MediaWiki についてのヘルプ
特別ページ
ツール
リンク元
関連ページの更新状況
ページ情報