2010年の The Computer Language Benchmarks Game からわかるように:
Goコンパイラーが実行用のネイティブコードを生成することを念頭に置いて、これはどうすればよいでしょうか?
Go用の未熟なコンパイラですか?または、Go言語に本質的な問題がありますか?
編集:
ほとんどの回答は、Go言語の本質的な遅さを否定し、問題は未熟なコンパイラーにあると主張しています。
したがって、私はいくつかのテストを行いました フィボナッチ数を計算するため :反復アルゴリズムはGo(freebsd、6g)でCのようにsame
速度で実行されます(O3を使用)オプション)。退屈な再帰はGo 2 times
Cよりも遅い(-O3オプションを使用、-O0を使用-同じ)。しかし、ベンチマークゲームのように10倍に落ちることはありません。
6gおよび8gコンパイラーは特に最適化されていないため、生成されるコードはそれほど高速ではありません。
それらは自分自身で高速に動作し、問題のないコードを生成するように設計されています(少し最適化されています)。 gccgo
はGCCの既存の最適化パスを使用し、Cとのより重要な比較を提供しますが、gccgoはまだ機能が完全ではありません。
ベンチマークの数値は、ほぼ完全に実装の品質に関するものです。実装が、ベンチマークが実際に必要としない言語機能をサポートするためにランタイムを費やす場合を除いて、彼らはそのような言語で大した量を持っていません。ほとんどのコンパイルされた言語では、十分に賢いコンパイラーが理論的には不要なものを取り除くことができますが、言語の実際のユーザーがその機能を使用しないプログラムを書くことはほとんどないため、デモをリギングする点があります。それらを完全に削除せずに邪魔にならないように移動する(たとえば、JITでコンパイルされたJavaで仮想呼び出し先を予測する)には注意が必要です。
FWIW、私がGoを見ていたときの非常に簡単なテスト(基本的に整数加算のループ)、gccgoはgcc -O0
およびgcc -O2
同等のCの場合Goは本質的に低速ではありませんが、コンパイラはまだすべてを実行しません。 10分前の言語にとっては驚くことではありません。
Go FAQ の次のリリースでは、次のようなものが表示されるはずです。
性能
GoがベンチマークXでパフォーマンスが悪いのはなぜですか?
Goの設計目標の1つは、同等のプログラムでCのパフォーマンスにアプローチすることですが、いくつかのベンチマークでは、テスト/ベンチのいくつかを含め、かなり不十分です。最も遅いのは、同等のパフォーマンスのバージョンがGoで利用できないライブラリに依存しています。たとえば、pidigitsは多精度の数学パッケージに依存しており、CバージョンはGoとは異なり、GMP(最適化されたアセンブラーで記述されています)を使用します。正規表現(regex-dnaなど)に依存するベンチマークは、本質的にGoのstopgap regexpパッケージとPCREなどの高度に最適化された成熟した正規表現ライブラリを比較しています。
ベンチマークゲームは広範なチューニングによって勝ち、ほとんどのベンチマークのGoバージョンに注意が必要です。比較可能なCおよびGoプログラム(逆相補がその一例です)を測定すると、このスイートが示すよりも2つの言語の生のパフォーマンスがはるかに近いことがわかります。
それでも、改善の余地があります。コンパイラーは優れていますが、より優れている可能性があり、多くのライブラリーは主要なパフォーマンス作業を必要とし、ガベージコレクターはまだ十分に高速ではありません(たとえそうであったとしても、不要なガベージを生成しないように注意すると大きな効果があります)。
そして、最近のメーリングリストのスレッドからの The Computer Benchmarks Game の詳細を以下に示します。
Computer Benchmarks Gameは単なるゲームであることに注意することが重要です。パフォーマンス測定とキャパシティプランニングの経験がある人々は、現実的で実際のワークロードと同様に慎重に一致します。彼らはゲームをしません。
私の答えは他の人たちほど技術的ではありませんが、それでも関連があると思います。 Goの学習を開始することにしたとき、コンピューターベンチマークゲームでも同じベンチマークを見ました。しかし、正直に言って、これらすべての合成ベンチマークは、Goがあなたにとって十分に高速であるかどうかを判断するという点では意味がありません。
Tornado + TornadIO + ZMQを使用して、メッセージサーバーをPythonで最近作成しました。最初のGoプロジェクトでは、Goでサーバーを書き直すことにしました。 Pythonバージョン、Goプログラムで4.7倍の速度向上がテストで示されています。注意してください、Goでは1週間しかコーディングしていません。 in Python 5年以上。
Goは、作業を続けるにつれて高速化するだけで、実際には、小さな小さな計算ベンチマークではなく、実際のアプリケーションでどのように機能するかにかかっていると思います。私にとって、Goは明らかにPythonで作成できるプログラムよりも効率的なプログラムになりました。それが、この質問に対する答えの私の見解です。
世の中変わったんだよ。
あなたの質問に対する現在の正しい答えは、行くのが遅いという概念に反対することだと思います。お問い合わせの時点で、あなたの判断は正当化されましたが、その後、パフォーマンスの面で多くの基盤が得られました。今では、Cほど高速ではありませんが、一般的な意味で10倍遅くはありません。
この執筆の時点で:
source secs KB gz cpu cpu load
reverse-complement
1.167x
Go 0.49 88,320 1278 0.84 30% 28% 98% 34%
C gcc 0.42 145,900 812 0.57 0% 26% 20% 100%
pidigits
1.21x
Go 2.10 8,084 603 2.10 0% 100% 1% 1%
C gcc 1.73 1,992 448 1.73 1% 100% 1% 0%
fasta
1.45x
Go 1.97 3,456 1344 5.76 76% 71% 74% 73%
C gcc 1.36 2,800 1993 5.26 96% 97% 100% 97%
regex-dna
1.64x
Go 3.89 369,380 1229 8.29 43% 53% 61% 82%
C gcc 2.43 339,000 2579 5.68 46% 70% 51% 72%
fannkuch-redux
1.72x
Go 15.59 952 900 62.08 100% 100% 100% 100%
C gcc 9.07 1,576 910 35.43 100% 99% 98% 94%
spectral-norm
2x
Go 3.96 2,412 548 15.73 99% 99% 100% 99%
C gcc 1.98 1,776 1139 7.87 99% 99% 100% 99%
n-body
2.27x
Go 21.73 952 1310 21.73 0% 100% 1% 2%
C gcc 9.56 1,000 1490 9.56 1% 100% 1% 1%
k-nucleotide
2.40x
Go 15.48 149,276 1582 54.68 88% 97% 90% 79%
C gcc 6.46 130,076 1500 17.06 51% 37% 89% 88%
mandelbrot
3.19x
Go 5.68 30,756 894 22.56 100% 100% 99% 99%
C gcc 1.78 29,792 911 7.03 100% 99% 99% 98%
ただし、バイナリツリーベンチマークでは残酷に苦しみます。
binary-trees
12.16x
Go 39.88 361,208 688 152.12 96% 95% 96% 96%
C gcc 3.28 156,780 906 10.12 91% 77% 59% 83%
CPUサイクルの使用に関するGoの効率はそれほど良くありませんが、Goの同時実行モデルは、たとえばJavaのスレッドモデルよりもはるかに高速で、C++スレッドモデルに匹敵します。
スレッドリングベンチマーク では、Goは16xJavaよりも高速でした。同じシナリオで、Go CSPはC++とほぼ同等でしたが、使用するメモリは4倍少なくなりました。
Go言語の大きな力は、70年代にTony Hoareによって指定された同時実行モデルであるCSP(Communicating Sequential Processes)であり、実装が簡単で、高度な同時実行ニーズに適合します。
JavaはGoやC++よりも高速であり、多くの場合Cよりも高速である可能性があるという2つの基本的な理由があります。
1)JITコンパイラー。 OOクラスであっても、実行時プロファイルに基づいて、複数のレベルで仮想関数呼び出しをインライン化できます。これは、静的にコンパイルされた言語では不可能です(記録されたプロファイルに基づいた新しい再コンパイルは、これは、反復アルゴリズムを含むほとんどのベンチマークにとって非常に重要です。
2)GC。 GCベースのメモリ割り当ては、mallocと比較してほぼ無料です。また、「無料」のペナルティはランタイム全体で償却できます。すべてのガベージを収集する必要がある前にプログラムが終了するため、多くの場合スキップされます。
GC/JVMを効率的にする非常に才能のある開発者が何百人もいます。 「すべてのコードよりも優れたコードを作成できる」と考えるのは愚かなことです。それは人間の自我の問題です-人間は、才能のある人間による適切な訓練によって、プログラムした人間よりもコンピュータのパフォーマンスが向上することを受け入れるのに苦労しています。
ちなみに、C++は、使用しない場合はOO機能を使用するとCと同じくらい高速になりますが、最初はCでのプログラミングにかなり近いです。
最も重要なことは、これらのテストの「速度の違い」は通常意味がないことです。 IOコストはパフォーマンスの違いよりも桁違いに大きいため、インタープリター言語でも、IOコストが常に勝ちます。ごくわずかです。システムはCPUバウンドです。
最後のメモとして、人々は「コンピューター言語ベンチマークゲーム」を「科学的尺度」と呼んでいます。テストは完全に欠陥があります。たとえば、nbodyのJavaテストを表示すると、同じOS /ハードウェアでテストを実行すると、Javaで約7.6秒、4.7秒が表示されますCの場合-これは妥当です-テストレポートの4倍の遅さではなく、クリックトラフィック、偽のニュース、サイトトラフィックを生成するように設計されています。
最後の最後のメモとして... Goを使用してテストを実行しましたが、7.9秒でした。 Goをクリックすると、Javaと比較され、JavaがCと比較されます)をクリックすると、真剣なエンジニアにとっては赤い旗になるはずです。
Java、Go、およびC++の実際の比較については、 https://www.biorxiv.org/content/10.1101/558056v1 spoiler alert、Javaが出てくるメモリ使用量とウォール時間を合わせてGoがトップになり、生のパフォーマンスでトップになります。
しばしば見落とされがちな事実は、JITコンパイルは、特に(実行時)遅延バインドされた関数またはメソッドに対して静的コンパイルである可能性があることだと思います。ホットスポットJITはRUNTIMEでインライン化するメソッドを決定し、現在実行中のCPUのキャッシュサイズ/アーキテクチャに合わせてデータレイアウトを調整する場合もあります。一般に、C/C++は、ハードウェアに直接アクセスすることで補うことができます(そして全体としては引き続きパフォーマンスが向上します)。 Goの場合、Cと比較して高レベルであるように見えるかもしれませんが、現在、実行時最適化システム/コンパイラがありません。 Goは、Go couldよりも速くJavaであるため、Goはポインター追跡をそれほど強制せず、データ構造の局所性を向上させ、より少ない割り当てを必要とします。
実際のところ、Goは設計時にエレガントで効率的であるだけでなく、実行時に優れたパフォーマンスを発揮します。重要なのは、適切なオペレーティングシステム、つまりLINUXを使用することです。 WindowsおよびMac OSでのパフォーマンスプロファイリングの結果は、優れたWordがないため、1〜2桁劣っています。
linuxでは、goランタイムは超高速で、c/c ++と完全に匹敵します。 WindowsとUNIXでのgoランタイムは同じリーグにはありません
Javaとの比較はそれほど重要ではありません。goはシステム開発とアプリケーション開発の両方に適用されます(Javaはアプリケーション開発のみのブルーカラーに似ています。)詳細に入力しますが、kubernetesのようなものがgoで書かれている場合、それはエンタープライズコンサルタント向けのおもちゃではないことに気づきます。
私はあなたが言及した妥協について一度も言及したグーグルを覚えていません。 goは、システムおよびアプリケーションレベルのプログラムを設計するための適切な設計、シンプル、エレガント、効率的であり、ポインター、効率的なメモリの割り当てと割り当て解除、実装の継承を誤用しやすいために生じる複雑さを回避し、コルーチンやその他の現代的なものを提供します高性能アプリケーションを時間と予算内で作成する方法。繰り返しになりますが、Linuxではgoは超高速です。