ホームページ バックエンド開発 C++ CとCは本当に速いですか?

CとCは本当に速いですか?

Dec 07, 2024 am 09:25 AM

C and C   are really so fast?

私がずっとプログラミングに取り組んでいると、速度の標準は C と C だと聞きます。最速中の最速で、アセンブリ コードに直接コンパイルされ、速度において C や C に匹敵するものはありません。そして、その一般的な信念に異議を唱える人は誰もいないようです。

コンピューティングパフォーマンス

数値を使った算術演算は、明らかに、C では他の言語よりも大幅に高速に動作する必要があります。でもそうですか?
少し前に、私は速度の実際の違いがどれほど大きいかを確認するために、さまざまな言語用の一連の簡単なベンチマークを作成することにしました。
アイデアは単純でした。単純な計算を使用して、ゼロから始まる 10 億の整数の合計を求めるというものです。一部のコンパイラ (rustc など) は、このような単純なサイクルを数式に置き換えます。もちろん、これは一定時間で評価されます。そのようなコンパイラでそれを回避するには。 ビット単位またはなど、数値を使用したコスト演算でも同様の操作を使用しました。
結果が出た後、とても驚きました。私の世界観はひっくり返り、プログラミング言語の速度について自分が知っていたすべてを再考する必要がありました。
以下の表に私の結果が表示されます:

Linux 64 ビット1.1 GHz CPU、4GB RAM

言語 コンパイラ/バージョン/引数 時間 Rust (
Language compiler/version/args time
Rust (bitwise or instead of ) rustc 1.75.0 with -O3 167 ms
C gcc 11.4.0 with -O3 335 ms
NASM 2.15.05 339 ms
Go 1.18.1 340 ms
Java 17.0.13 345 ms
Common Lisp SBCL 2.1.11 1 sec
Python 3 pypy 3.8.13 1.6 sec
Clojure 1.10.2 9 sec
Python 3 cpython 3.10.12 26 sec
Ruby 3.0.2p107 38 sec
の代わりに ビット単位または ) rustc 1.75.0 (-O3 あり) 167 ミリ秒 C gcc 11.4.0 (-O3 あり) 335 ミリ秒 NASM 2.15.05 339 ミリ秒 行く 1.18.1 340 ミリ秒 Java 17.0.13 345 ミリ秒 一般的な Lisp SBCL 2.1.11 1 秒 Python 3 pypy 3.8.13 1.6 秒 Clojure 1.10.2 9 秒 Python 3 cpython 3.10.12 26 秒 ルビー 3.0.2p107 38 秒 テーブル>

ここにあるすべてのテスト ソース:
https://github.com/Taqmuraz/speed-table

ご覧のとおり、C は Java よりもそれほど高速ではなく、その差は約 3% です。また、他のコンパイル言語は算術演算のパフォーマンスが C に非常に近いことがわかります (Rust はさらに高速です)。 JIT コンパイラ でコンパイルされた動的言語は、より悪い結果を示します。主な原因は、算術演算がそこで動的にディスパッチされる関数にラップされているためです。
JIT コンパイラなしで解釈された動的言語は最悪のパフォーマンスを示しますが、驚くべきことではありません。

メモリ割り当てパフォーマンス

あの惨敗の後、C ファンは、GC を要求せずにシステムから直接メモリを割り当てるため、C でのメモリ割り当てが非常に高速であると言うでしょう。
今後も、コンテキストに応じて、GC という用語を ガベージ コレクターマネージド ヒープ の両方として使用します。
では、なぜ人々は GC がとても遅いと考えるのでしょうか?実際、GC には事前に割り当てられたメモリがあり、割り当ては単にポインタを右に移動するだけです。ほとんどの場合、GC は、C の memset と同様に、システム コールを使用して割り当てられたメモリをゼロで埋めるため、一定の時間 がかかります。 C でのメモリ割り当てには、システムとすでに割り当てられているメモリに依存するため、不定の時間がかかります。
しかし、この知識を考慮しても、Java からそれほど良い結果は期待できませんでした。これは次の表に示すとおりです。

1.1 GHz 2 cores, 4 GB RAM
Running tests on single thread.
Result format : "Xms-Yms ~Z ms" means tests took from X to Y milliseconds, and Z milliseconds in average
1.1 GHz 2 コア、4 GB RAM 単一スレッドでテストを実行しています。 結果の形式 : 「Xms-Yms ~Z ms」は、テストに X から Y ミリ秒、平均で Z ミリ秒かかったということを意味します テーブル>

整数配列の割り当て

integers array size times Java 17.0.13 new[] C gcc 11.4.0 malloc Common Lisp SBCL 2.1.11 make-array
16 10000 0-1ms, ~0.9ms 1-2ms, ~1.2ms 0-4ms, ~0.73ms
32 10000 1-3ms, ~1.7ms 1-3ms, ~1.7ms 0-8ms, ~2.ms
1024 10000 6-26ms, ~12ms 21-46ms, ~26ms 12-40ms, ~7ms
2048 10000 9-53ms, ~22ms 24-52ms, ~28ms 12-40ms, ~19ms
16 100000 0-9ms, ~2ms 6-23ms, ~9ms 4-24ms, ~7ms
32 100000 0-14ms, ~3ms 10-15ms, ~11ms 3-8ms, ~7ms
1024 100000 0-113ms, ~16ms 234-1156ms, ~654ms 147-183ms, ~155ms
2048 100000 0-223ms, ~26ms 216-1376ms, ~568ms 299-339ms, ~307ms

1 つの整数フィールドを備えたクラス Person のインスタンスを割り当てます。

how many instances Java 17.0.3 new Person(n) C g 11.4.0 new Person(n)
100000 0-6ms, ~1.3ms 4-8ms, ~5ms
1 million 0-11ms, ~2ms 43-69ms, ~47ms
1 billion 22-50ms, ~28ms process terminated

ここにあるすべてのテスト ソース:
https://github.com/Taqmuraz/alloc-table

そこで私は合計 4 つの言語 (C、C、Java、Lisp) をテストしました。また、 GC を使用した言語は、 C や C よりもはるかに厳密にテストしましたが、常に良い結果を示します。たとえば、Java では仮想関数呼び出しを通じてメモリを割り当てているため、静的に最適化されない可能性があります。また、Lisp では割り当てられた配列の最初の要素をチェックしているため、コンパイラは割り当て呼び出しをスキップしません。

メモリの解放

C ファンは依然として自分たちの信念を守ろうとする動機を持っているため、「はい、メモリの割り当ては速くなりますが、その後は解放する必要があります。」と言います。
真実。そして突然、GC は C よりも速くメモリを解放します。しかし、どのようにしてメモリを解放するのでしょうか? GC から 100 万回の割り当てを行ったが、その後、プログラム内で参照されるオブジェクトが 1000 個だけになったと想像してください。そして、それらのオブジェクトがその長いメモリ全体に分散されているとします。 GC はスタック トレースを実行し、これら 1000 個の「生きている」オブジェクトを見つけて、それらを前の世代のヒープ ピークに移動し、最後のオブジェクトの後にヒープ ピーク ポインタを置きます。以上です。
したがって、割り当てるオブジェクトの数に関係なくGCの作業時間は、後に保持するオブジェクトの数によって決まります。
そして、それとは逆に、C では割り当てられたメモリをすべて手動で解放する必要があるため、メモリを 100 万回割り当てた場合は、同様に 100 万回の解放呼び出しを行う必要があります (そうしないとメモリ リークが発生します)。つまり、GCO(1)-O(n) と C の O(n) またはそれより悪い (n) に対するものです。は以前に発生した割り当ての数です。

まとめ

そこで、C および C に対するガベージ コレクション言語の勝利を確固たるものにしたいと考えています。概要表は次のとおりです:

要求 GC を使用する言語 C/C 算術
demands languages with GC C/C
arithmetic fast with JIT fast
allocating memory fast O(1) slow
releasing memory fast O(1) best case, O(n) worst case O(n) or slower
memory safe yes no
JIT による 高速化 速い メモリを割り当てています 速い O(1) 遅い メモリを解放しています 高速 O(1) 最良の場合、O(n) 最悪の場合 O(n) またはそれより遅い メモリセーフ はい いいえ テーブル>

これで、ガベージ コレクションは必要悪ではなく、私たちが望むだけの最高のものであることがわかるかもしれません。それは私たちに安全性パフォーマンス両方をもたらします。

Cへのトリビュート

C は私のテストでは悪い結果を示しましたが、依然として重要な言語であり、独自の応用分野があります。私の記事はCの拒絶や抹殺を目的としたものではありません。 C は悪くはありませんが、人々が思っているほど優れているわけではありません。多くの優れたプロジェクトが崩壊したのは、一部の人が Java の代わりに C を使用することを決めたという理由だけです。たとえば、C の方がはるかに高速で、Java はガベージ コレクションのせいで信じられないほど遅いと言われてきたためです。非常に小さく単純なプログラムを作成する場合には、C が適しています。ただし、C を使用して複雑なプログラムやゲームを作成することは決してお勧めしません。

Cは違うよ

C は単純ではなく、柔軟性がなく、構文が多重定義されており、仕様が複雑すぎます。 C でプログラミングすると、自分のアイデアを実装することはできませんが、90% の確率でコンパイラ エラーやメモリ エラーと戦うことになります。
この記事は C を拒否することを目指しています。速度とパフォーマンスは人々がソフトウェア開発でこの言語を使用するための言い訳にすぎないからです。 C を使用すると、時間、プログラムのパフォーマンス、精神的健康で対価を支払うことになります。したがって、C と他の言語のどちらかを選択する場合は、最後の言語を選択してください。

以上がCとCは本当に速いですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

Video Face Swap

Video Face Swap

完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

C言語データ構造:ツリーとグラフのデータ表現と操作 C言語データ構造:ツリーとグラフのデータ表現と操作 Apr 04, 2025 am 11:18 AM

C言語データ構造:ツリーとグラフのデータ表現は、ノードからなる階層データ構造です。各ノードには、データ要素と子ノードへのポインターが含まれています。バイナリツリーは特別なタイプの木です。各ノードには、最大2つの子ノードがあります。データは、structreenode {intdata; structreenode*left; structreenode*右;}を表します。操作は、ツリートラバーサルツリー(前向き、順序、および後期)を作成します。検索ツリー挿入ノード削除ノードグラフは、要素が頂点であるデータ構造のコレクションであり、近隣を表す右または未照明のデータを持つエッジを介して接続できます。

C言語ファイルの操作問題の背後にある真実 C言語ファイルの操作問題の背後にある真実 Apr 04, 2025 am 11:24 AM

ファイルの操作の問題に関する真実:ファイルの開きが失敗しました:不十分な権限、間違ったパス、およびファイルが占有されます。データの書き込みが失敗しました:バッファーがいっぱいで、ファイルは書き込みできず、ディスクスペースが不十分です。その他のFAQ:遅いファイルトラバーサル、誤ったテキストファイルエンコード、およびバイナリファイルの読み取りエラー。

C言語関数の基本的な要件は何ですか C言語関数の基本的な要件は何ですか Apr 03, 2025 pm 10:06 PM

C言語関数は、コードモジュール化とプログラム構築の基礎です。それらは、宣言(関数ヘッダー)と定義(関数体)で構成されています。 C言語は値を使用してパラメーターをデフォルトで渡しますが、外部変数はアドレスパスを使用して変更することもできます。関数は返品値を持つか、または持たない場合があり、返品値のタイプは宣言と一致する必要があります。機能の命名は、ラクダを使用するか、命名法を強調して、明確で理解しやすい必要があります。単一の責任の原則に従い、機能をシンプルに保ち、メンテナビリティと読みやすさを向上させます。

C言語の関数名定義 C言語の関数名定義 Apr 03, 2025 pm 10:03 PM

C言語関数名の定義には、以下が含まれます。関数名は、キーワードとの競合を避けるために、明確で簡潔で統一されている必要があります。関数名にはスコープがあり、宣言後に使用できます。関数ポインターにより、関数を引数として渡すか、割り当てます。一般的なエラーには、競合の命名、パラメータータイプの不一致、および未宣言の関数が含まれます。パフォーマンスの最適化は、機能の設計と実装に焦点を当てていますが、明確で読みやすいコードが重要です。

C言語関数の概念 C言語関数の概念 Apr 03, 2025 pm 10:09 PM

C言語関数は再利用可能なコードブロックです。彼らは入力を受け取り、操作を実行し、結果を返すことができます。これにより、再利用性が改善され、複雑さが軽減されます。関数の内部メカニズムには、パラメーターの渡し、関数の実行、および戻り値が含まれます。プロセス全体には、関数インラインなどの最適化が含まれます。単一の責任、少数のパラメーター、命名仕様、エラー処理の原則に従って、優れた関数が書かれています。関数と組み合わせたポインターは、外部変数値の変更など、より強力な関数を実現できます。関数ポインターは機能をパラメーターまたはストアアドレスとして渡し、機能への動的呼び出しを実装するために使用されます。機能機能とテクニックを理解することは、効率的で保守可能で、理解しやすいCプログラムを書くための鍵です。

c-subscript 3 subscript 5 c-subscript 3 subscript 5アルゴリズムチュートリアルを計算する方法 c-subscript 3 subscript 5 c-subscript 3 subscript 5アルゴリズムチュートリアルを計算する方法 Apr 03, 2025 pm 10:33 PM

C35の計算は、本質的に組み合わせ数学であり、5つの要素のうち3つから選択された組み合わせの数を表します。計算式はC53 = 5です! /(3! * 2!)。これは、ループで直接計算して効率を向上させ、オーバーフローを避けることができます。さらに、組み合わせの性質を理解し、効率的な計算方法をマスターすることは、確率統計、暗号化、アルゴリズム設計などの分野で多くの問題を解決するために重要です。

CSウィーク3 CSウィーク3 Apr 04, 2025 am 06:06 AM

アルゴリズムは、問題を解決するための一連の指示であり、その実行速度とメモリの使用量はさまざまです。プログラミングでは、多くのアルゴリズムがデータ検索とソートに基づいています。この記事では、いくつかのデータ取得およびソートアルゴリズムを紹介します。線形検索では、配列[20,500,10,5,100,1,50]があることを前提としており、数50を見つける必要があります。線形検索アルゴリズムは、ターゲット値が見つかるまで、または完全な配列が見られるまで配列の各要素を1つずつチェックします。アルゴリズムのフローチャートは次のとおりです。線形検索の擬似コードは次のとおりです。各要素を確認します:ターゲット値が見つかった場合:return true return false c言語実装:#include#includeintmain(void){i

C#対C:歴史、進化、将来の見通し C#対C:歴史、進化、将来の見通し Apr 19, 2025 am 12:07 AM

C#とCの歴史と進化はユニークであり、将来の見通しも異なります。 1.Cは、1983年にBjarnestrostrupによって発明され、オブジェクト指向のプログラミングをC言語に導入しました。その進化プロセスには、C 11の自動キーワードとラムダ式の導入など、複数の標準化が含まれます。C20概念とコルーチンの導入、将来のパフォーマンスとシステムレベルのプログラミングに焦点を当てます。 2.C#は2000年にMicrosoftによってリリースされました。CとJavaの利点を組み合わせて、その進化はシンプルさと生産性に焦点を当てています。たとえば、C#2.0はジェネリックを導入し、C#5.0は非同期プログラミングを導入しました。これは、将来の開発者の生産性とクラウドコンピューティングに焦点を当てます。

See all articles