私は数年プログラミングをしていて、Javaで始めました。その間に、さまざまな情報源がJavaが何らかの形で劣った言語であると主張しています。私はそうです。 mそれぞれの言語には長所と短所があることをよく認識していますが、私が読んだことのある多くのJavaは日付が付けられているようです。
Javaが劣っている最もよく引用される理由は、C++などの他のネイティブにコンパイルされた言語よりもはるかに遅いためです。多くの人が=の使用についてMinecraftを開発した)ゲームデザイナーNotchを批判しますJavaパフォーマンス部門が明らかに不足しているため。私は知っていますJava当時はかなり遅くなりましたが、特にJITコンパイル以降、多くの改善がありました。
私はJavaを今日の言語としていくつかの客観的な意見を得たいので、私の質問は4つのパートに分かれています。
パフォーマンス。
a。今日のJavaの速度はC++と比べてどうですか?
b。 Javaを使用して最新のAAAタイトルを作成することは可能ですか?
c。 Javaであるとすれば、C++よりも遅いのはどの領域ですか?(つまり、数値の処理、グラフィックス、またはそのすべて)
Javaは現在、コンパイル済み言語またはインタープリター言語と見なされていますか?
初期の頃から対処されてきたJavaの主な欠点は何ですか?
Javaでまだ対処されていない主な欠点は何ですか?
編集:
明確にするためだけに、私はこれを作成していませんJava vs C++、明らかに平均してc ++はJavaよりも少し高速です。比較するために何かが必要ですJava =この時点での言語としての成熟度に関してc ++は永遠に存在していたので、私は比較の良い点になると思いました。
a。今日のJavaの速度はC++と比べてどうですか?
測定が難しい。実装の速度の主要な部分であるメモリアロケータは、JavaとC++では非常に異なるアルゴリズムです。コレクタの非決定的な性質により、取得が非常に困難になります。 C++の確定的なメモリ管理と比較して、意味のあるパフォーマンスデータ。コレクターの状態を特定することはできないためです。これは、それらを意味のある形で比較するベンチマークを書くことが非常に難しいことを意味します。一部のメモリ割り当てパターンは、 GC、一部はネイティブアロケーターではるかに高速に実行されます。
ただし、Java GCはeveryの状況で高速に実行する必要があります。ネイティブアロケータただし、より適切なものに交換することができます。私は最近 SO にC#Dictionary
を実行できる理由について質問をしました(私の場合は0.45ミリ秒)マシン)で実行された同等のstd::unordered_map
(私のマシンでは10ミリ秒)と比較します。ただし、アロケータとハッシュをより適切なものに交換するだけで、マシンでその実行時間を0.34ミリ秒に短縮しました。元のランタイムのことです。Javaでそのようなカスタム最適化を実行することは決してできません。これが実際の違いを生むことができる優れた例は、スレッド化です。TBBのようなネイティブスレッドライブラリは、大量のスレッドキャッシュアロケータを提供します。多くのスレッドで多くの割り当てを処理する場合、従来のアロケーターよりも高速です。
今、多くの人々がJITの改善とJITがより多くの情報を持っている方法について話します。確かに、それは本当です。しかし、最終的なプログラムの実行時間の観点から見ると、コンパイラーは、実行する時間とスペースが無限にあるため、C++コンパイラーが引き寄せることができる距離にまだそれほど遠くはありません。 JITがプログラムを最適化するための最善の方法について考えているすべてのサイクルとすべてのバイトは、プログラムが実行に費やしておらず、独自のメモリニーズに使用できないサイクルです。
さらに、コンパイラーとJITの最適化では、特定の最適化を証明できない場合が常にあります(特に、エスケープ分析などの場合)。 C++では、値がスタックanywayにあるため、コンパイラーはそれを実行する必要はありません。さらに、連続したメモリのような単純なものがあります。 C++で配列を割り当てる場合は、単一の連続した配列を割り当てます。 Javaで配列を割り当てる場合、配列はどこも指すことができるポインタでのみ満たされているため、連続していません。これは、二重の間接参照のメモリと時間のオーバーヘッドだけでなく、キャッシュのオーバーヘッドでもあります。この種のことは、Javaの言語セマンティクスが、同等のC++コードよりも低速でなければならないことを強制するだけです。
結局のところ、私の個人的な経験では、Javaは平均してC++の約半分の速度になる可能性があります。ただし、非常に包括的なベンチマークスイートがないと、パフォーマンスステートメントをバックアップする方法は現実的にありません。根本的に異なるアルゴリズムが含まれています。
b。 Javaを使用して最新のAAAタイトルを作成することは可能ですか?
ここでは「ゲーム」という意味で、チャンスではないと思います。まず、ほぼすべての既存のライブラリとインフラストラクチャターゲットC++として、すべてをゼロから作成する必要があります。それ自体を不可能にすることはしませんが、それは確かに実現不可能に向けて確実に貢献することができます。第2に、C++エンジンでさえ、既存のコンソールの小さなメモリ制約にほとんど適合できません(それらのコンソールにJVMが存在する場合でも)、PCゲーマーはメモリにもう少し期待しています。 C++では、パフォーマンスの高いAAAゲームを作成するのは非常に困難です。Javaでそれを実現する方法はわかりません。コンパイルされていない言語でかなりの時間を費やしたAAAゲームを書いた人はいません。それ以上に、それは単に非常にエラーが発生しやすくなります。たとえば、GPUリソースを処理する場合、確定的な破棄が不可欠です。Javaでは、基本的にそれらをmalloc()およびfree()する必要があります。
c。 Javaであるとすれば、C++よりも遅いのはどの領域ですか?(つまり、数値の処理、グラフィックス、またはそのすべて)
私は間違いなくオールラウンドに行きます。すべてのJavaオブジェクトの強制参照の性質は、JavaがC++の場合よりもはるかに多くの間接参照と参照を持っていることを意味します。配列で以前に示した例では、ただし、たとえば、すべてのメンバーオブジェクトにも適用されます。C++コンパイラーが一定時間内にメンバー変数を検索できる場合、Javaランタイムは別のポインターに従う必要があります。アクセスが増えるほど、 、これは遅くなるだろうし、JITがそれについてできることは何もない。
C++がメモリの一部をほぼ瞬時に解放して再利用できるところでは、Javaでコレクションを待つ必要があります。そして、その部分がキャッシュから消えず、本質的にメモリが多いほど、キャッシュとページングのパフォーマンスが低下します。次に、ボックス化やボックス化解除などのセマンティクスを確認します。Javaでは、intを参照する場合は、動的に割り当てる必要があります。これは、C++セマンティクスと比較すると、本質的に無駄です。
次に、ジェネリック問題があります。 Javaでは、実行時継承を通じてのみ、汎用オブジェクトを操作できます。 C++では、テンプレートのオーバーヘッドは文字通りゼロです。何かJavaは一致しません。これは、Javaのすべての汎用コードが、 C++。
そして、あなたは未定義の振る舞いに行きます。彼らのプログラムがUBを示すとき、誰もがそれを憎み、誰もがそれが存在しなかったことを望みます。ただし、UBは基本的に、Javaには存在し得ない最適化を可能にします。 UBに基づく最適化について説明している this の投稿をご覧ください。動作を定義しないことは、実装がより多くの最適化を行い、C++では定義されないがJavaで定義される条件をチェックするために必要なコードを削減できることを意味します。
基本的に、Javaのセマンティクスは、C++よりも遅い言語であることを示しています。
Javaは現在、コンパイル済み言語またはインタープリター言語と見なされていますか?
どちらのグループにも当てはまりません。マネージドはそれ自体が別のカテゴリであると言いますが、コンパイルされた言語というよりはインタープリター型言語に近いと思います。さらに重要なことは、JVMとCLRの2つの主要な管理対象システムのみがほとんどあり、 "管理対象"と言うと、それは十分に明示的です。
初期の頃から対処されてきたJavaの主な欠点は何ですか?
自動ボクシングとアンボクシングは私が知っている唯一のものです。ジェネリックスはsomeの問題を解決しますが、多くの問題からはほど遠いです。
Javaでまだ対処されていない主な欠点は何ですか?
彼らのジェネリックは非常に非常に弱いです。 C#のジェネリックはかなり強力です-もちろん、どちらも完全なテンプレートではありません。確定的破壊は、もう1つの大きな欠如です。あらゆる形式のラムダ/クロージャも大きな問題です。Javaで機能するAPIを忘れることがあります。そしてもちろん、それらを必要とする領域には、常にパフォーマンスの問題があります。
まず、プログラミング言語について真に中立的な意見を述べることはだれにとってもほぼ不可能であるという条件から始めます。 2つの言語について十分に理解し、それらについて有意義なコメントをすることができる場合、どちらか一方を優先することはほぼ避けられません。公平な警告として、私はJavaよりもC++を好みます。これは間違いなく私のコメントに少なくともある程度影響を与えます。
1a。速度:C++またはJava=のいずれかから得られる速度は、通常、それを使用するプログラマーのスキルよりも言語またはその実装に依存しません。最終的に、C++はおそらくcanより多くの場合速度で勝つことができますが、あなたが書くコードの違いは本当に重要です。
1b。はい、たぶん。同時に、C++はすでに十分に確立されており、ほとんどのゲームスタジオは、Javaへの切り替えに煩わされるだけの十分な利点があるとは思えません。
1c。これに対する完全な答えは、おそらく大きなボリュームを埋めることができます。 C++は一般に、リソースを制限することでより効果的になります。 Java=は、(たとえば)大量の「予備」メモリを利用できることから、より多くの利益を得ます。
2。実行が遅いこととガベージコレクションが遅いことは、おそらく最も明白な2つでしょう。初期のウィンドウ処理ライブラリ(AWT)は非常に不格好でした-Swingは大きな改善でした。
3。冗長。オペレーターの過負荷の欠如。ガベージコレクションの使用。多重継承の欠如。 Javaジェネリックは極端にC++テンプレートと比較して制限されています。
これらの不利な点のいくつか(すべて?)(特にガベージコレクションの使用ですが、他の不利な点もある)は、Javaの多くの利点として見られます。唯一の可能な例外は、その冗長性です。冗長性の状況は少しずつ改善されていますが、確かにJava優勝したコードゴルフコンテストは頻繁には見られません。通常のコードでは、非常に多くのコードを使用する傾向があります。読みやすく理解しやすいと考える人が少なくとも数人いるのではないかと思われます。
まず、いくつかのコンテキスト、私のC++は非常に錆びているので、Javaでの私の経験のほとんどは、とにかくはるかに多くのリンゴの比較であるC#での私の最近の経験に関連しています。
a。今日のJavaの速度はC++と比べてどうですか?
SO質問 なぜJava遅いという評判があったのですか? 質問全体は、Jeff Atwoodのブログ投稿 Gorilla vs. Shark によって色分けされています。 Péter&Christopherに感謝します。
b。 Javaを使用して最新のAAAタイトルを作成することは可能ですか?
それは、開発者の優先順位と開発者のスキルに依存します。さらに、どちらか一方または両方の状況ではないため、タイトルの異なる部分では、実装する言語の異なる異なるものが必要になる可能性があり、異種の言語環境につながります。
私は最近、多くのゲームがPython環境をロードしているときにそれらをロードしていることを言及しています。そして コースの馬 は、 (たとえば)ホリデーシーズンに間に合うようにタイトルを取得したいと考えています。
c。 Javaであるとすれば、C++よりも遅いのはどの領域ですか?(つまり、数値の処理、グラフィックス、またはそのすべて)
パフォーマンスの低いコードを任意の言語で作成できますが、一部の言語では適切な選択が容易になりますが、他の言語では 自分の手で押し上げる が得られる傾向があります。 Javaは前者のカテゴリーに該当し、C++は間違いなく後者のカテゴリーに該当します。
彼らが言うように、大きな力には大きな責任があります(ヒープを完全にねじ込む能力は言うまでもありません* 8 ')。
ほとんどの人がそれを何であると考えるかは言えませんが、多くの人はコンパイルされた言語と解釈された言語の違いを知っており、過去20年間洞窟に住んでいませんでした年は、JIT( ジャストインタイム )コンパイラがJavaエコシステムの重要な部分であるため、おそらく考慮される可能性が高いことも知っています。最近コンパイルされました。
私はかなり最近Javaに変換しているので、それがどのように進化したかについてはほとんど理解できません。しかし、興味深いのは Java:The Good Parts のような本があり、最近好まれるべき言語の部分の方向に人々を導き、地域から人々を遠ざけることを目的としていることです。廃止予定であるか、廃止すべきです。
私の考えでは、Java=の問題の1つは、新機能の採用が遅いことです。
Javaにアクセスして Wikipediaの比較ページ を見ると、これらは私にとって際立ったものです:
var
)は構文上の砂糖のように見えるかもしれませんが、複雑なジェネリック型がある場合、コードを作成できます価値のない重複の多くを削除することで、より明確になります。struct
を完全なクラスで使用するための引数がある場合があります。unsafe
コードへのアクセス。あなたはsoこれに注意する必要があります。そのため、リンゴとリンゴを比較する場合でも、Javaは遅れていると見なされます。
Javaで発生する他の2つの大きな問題は、悪質な起動遅延と、(一部のJVMの場合) ヒープをマイクロ管理する および permanent generation heap 。C#アプリケーションでは常に即座に開始され、仮想マシンに割り当てられた事前に割り当てられたプールからではなく、システムメモリプールから割り当てられたので、ヒープについて考える必要はありませんでした。 。
質問の最初の部分に答えるのに役立つ情報源を紹介します。プログラミング言語が飛び出る http://shootout.alioth.debian.org/u64q/which-programming-languages-are-fastest.php は、言語が互いにどの程度高速に比較されているかを確認するのにかなり良い情報源です。異なるカテゴリでフィルタリングして、言語が他の分野よりも優れている領域を確認することもできます。Javaは、数年前よりもはるかに高速です。
1)私がJavaで得られるUXについて厳密に話すと、遅いように感じます。なぜなのか本当に言えません。私はまだJavaベースのデスクトップアプリケーションに出会う必要はありません。速度が遅く感じません)、Java以外の高速な代替手段があります。 Javaは純粋な計算速度で非常に高速になる可能性があり、インターネットはそれを証明するベンチマークでいっぱいです。しかし、Javaアプリの起動時間と応答性は彼らのGUIはまだIMHOを改善していません。
結局のところ、速度はそれほど問題ではありません。ハードウェアがますます速くなっているだけでなく、ソフトウェアが実行する限り、ほとんどの人は驚くほどほとんど気にしていません。ソフトウェアが何をすべきか、対話に費やされた時間と待機に費やされた時間の比率は妥当です。
2)この区別は最近非常に不鮮明になり、価値はほとんどありません。
3 + 4)Java実際にはかなりの変更がありました。一部の人々は、これらの変更により、異質な機能を追加することによってJavaの純粋に単純化された哲学が損なわれていると主張しています。客観的に言うのは本当に難しいです。私にとって、Javaは不必要に冗長で制限があり、機能が貧弱ですが、他の人々はこれらの特性を快適な曖昧さ、安全性、明快さと見なしています。
したがって、個人的にJavaを使用しないのはこれらのことですが、私が見逃したものを単に追加することは考えていませんJavaは良い考えです。たくさんあります。私がJVMで実行したい言語Javaそれらに近づくように曲げることは、Javaの目的を無効にするだけです。
Java=の問題は、足で自分を撃つことを防ぐように設計されていることです。高貴な原因ですが、すべての制限があるため、ストラップが付いているため、可能性は低くありません。安全な足の上でつまずき、自分の安全のために背中の後ろに手を縛られて自分を支えられず、最後に死ぬ。
ある意味で、JavaはC++への応答でした。これにより、自分だけでなく、他の世界も吊るすのに十分なロープが得られます。それがすべてのロープです。それはカウボーイにとってとても魅力的です。すべてのその自由とすべてのその力。
簡単に言えば、これは本当に好みの問題です。
ただし、要点は、Javaの代わりにC++を使用すると、独自の制限を自由に選択できることです。または、あなたが持っているすべてのコントロールを真剣に実行し、仲間を完全に混乱させる危険を冒します:
「cout」が「Hello world」の時間だけ左にシフトし、そこで止まったのを見ました。
—スティーブ・ゴネス
そのため、Javaは演算子のオーバーロードを提供しないことを選択しました。もちろん、これにより、関数ポインタとリストを掛け合わせることでコードが難読化されるのを防ぐことができます。しかし同時に、他の人が通常の演算子で幾何学/代数計算を実行するのを防ぎます。 _(v1 * v2 / scale) + (v3 * m)
_は、実際にv1.multiply(v2).divide(scale).add(v3.multiply(m))
よりたくさん明確です。これが3Dグラフィックスと計算を扱う人々を先送りにする理由がわかります。
Javaはガベージコレクションを課すことを選択しましたが、C++では選択できます。本当に掘り下げて、ハードウェアに近づくことができます。データを構造体に密にパックできます。 高速逆平方根 などのダークマジックを実行できます。テンプレートを使用して、地球上で最も複雑で不可解なメタプログラミングを実行できます。しかし、それはまた、あなたが迷子になり、作成したすべての混乱をデバッグしたり、まったく役に立たないコンパイラエラーを調べたりして、何時間も費やす可能性があることも意味します。
しかし、本当に習得している言語の部分のみを使用する規律がある場合は、Javaコードと同じくらい安全にC++コードを記述できますが、次のオプションがあります。徐々に前進します。
したがって、Javaで最先端のソフトウェアを書くことを技術的に妨げるものは何もありませんが、多くの開発者は優れたソフトウェアを書くことに情熱を傾け、その間、Java言語として提供します。
しかし、世界は、次の大きなものを作成する人々だけで構成されるのではなく、与えられた電力の使用を彼らの範囲内でのみ制限する人々だけで構成されるのではありません。それを制御します。 IMHOJavaは、快適な方法で安定した結果を生成したい人に最適です
ガベージコレクションは重要です。ときどき、GCは(ヒープのサイズに応じて)数百ミリ秒間他のすべてをロックアウトし、主要なコレクションを実行します。タイミングの制約がない場合はこれで問題ありませんが、遅れることが失敗を意味する場合、これはショーストッパーです。リアルタイムJavaとリアルタイムOSにお金を使うことができますが、GCCと標準Linuxを使用するだけでこれらの問題は発生しません。
予測できないランダムな一時停止がなければ、Javaは最近のほとんどの事柄に対しておそらく十分高速です。そして、GC設定などを微調整するのに何ヶ月も費やすなら、たぶん、たぶん、それを長く動作させることができます顧客があなたに小切手を切るのに十分です。