Couchbaseの作者Damien Katz氏は,C言語はバックエンドプログラミングにおいて現在でも優れた言語である,という意見を持っている。しかし他の開発者は,C言語はあまりにも欠陥が多いとしてC++やJavaを支持するもの,あるいはいずれも好まないというものなどさまざまだ。
CouchDB の開発者であるDamien Katz氏は,The Unreasonable Effectiveness of C と題した先日のブログ記事において,C言語がバックエンドのための優れた言語であると断言した。氏はC++やJava,さらにはErlangやRubyのようなより現代的な言語よりも,今後もC言語を支持していくつもりだという。ただし単純に,C言語を他のどれよりも優れた言語だと言っている訳ではない。"言語自体のパフォーマンスと信頼性が重視される場面においては,C言語に比類する言語は皆無である",別の記事でこのように述べて,自身の立場をより明確にしている。
CouchDBでは当初Erlangを多用していたが,"Erlang VMのクラッシュのせいで2人月以上を" 浪費した結果,Erlangに不満を覚えるようになったのだという。
Erlangのコア実装に何かがあることを突き止めるまで,相当な時間を無駄にしました。何が起きているのか,どうしてなのか,さっぱり分からず,私たちのプラグインCコードに何か問題があるのだろう,何とかして見つけ出して修正しなければ,と思っていたのです。でも,そうではありませんでした。Erlangのコア部分に,レースコンディションに関するバグがあったのです。問題の所在が分かったのは,Erlangのコアを調査してからでした。私はこれを,コンピュータを過度に抽象化している言語すべてに共通する,根本的な問題だと思うのです。
この問題とパフォーマンス上の理由から,Katz氏は "Couchbaseのコードの大部分をC言語で" 段階的に書き直すと同時に,以降の機能追加においても,C言語を最優先の選択肢にすることにした。すると興味深いことに,C言語には "問題の発生する時期や,それをデバッグして修正する方法を予想する上で大きなメリットのあることが明らかになりました。長期的な視野に立てば,C言語の方が生産性が高かったのです。"
バックエンド開発において,C++やJavaといった高レベルな言語よりもC言語が優れている理由として,Katz氏は次のようなことを挙げている。
- 表現力 – "C言語のシンタクスとセマンティクスは非常に強力で,表現性に富んでいます。これにより,高レベルのアルゴリズムと低レベルのハードウェアを同時に考えることも容易です。シンプルなセマンティクスと強力なシンタクスを備えることで,認知面での負担が著しく低減されるため,プログラマが本当に重要なものに集中できるのです。"
- シンプルさ – "C言語は弱い静的型付け言語ですが,その型システムは非常にシンプルです。 ... 一見短所に思われるこの部分が,実は長所なのです – C言語のAPIは非常にシンプルでコンパクトです。大規模なフレームワークではなく,シンプルな型とライトウェイトな抽象化を備えた,コンパクトなライブラリを生み出す文化がC言語にはあります。"
- 実行速度とメモリフットプリント – "小規模なベンチマーク,フルスタックのベンチマークのどちらにおいても,C言語は最速のプログラム言語です。実行時の速度だけではありません。メモリ使用量と起動時間においても,C言語は一貫してもっとも効率的な言語なのです。さらにメモリ容量と速度のトレードオフが必要な場合でも,C言語は詳細を隠すことがありませんから,どちらについても適確な判断を下すことができます。"
- 開発サイクルの向上 – "開発者の効率と生産性を考える上で非常に重要なのが,"ビルド,実行,デバッグ" というサイクルです。このサイクルが速ければ,よりインタラクティブな開発が可能になるとともに,タスクに費やす時間もより多く確保できます。C言語は主要な静的型付け言語の中で,もっとも速い開発インタラクティビティを備えた言語なのです。"
- デバッグ – "純粋なC言語コードならば,コールスタック,変数,引数,スレッドローカル,グローバルなど,基本的にメモリ内をすべて見ることができます。長期間稼働するサーバプロセスで,何日も稼働した後でないと再現しないような問題が発生しているような場合には,これは本当に役立ちます。高レベル言語を使うとこのようなコンテキストが失われてしまうため,大変な苦労を覚悟しておかなければなりません。"
- クロスプラットフォーム – "標準化されたバイナリインターフェース(ABI/Application Binary Interface)" があって,あらゆるOSや言語,プラットフォームでサポートされています。その上ランタイムや,その他固有のオーバーヘッドを必要としません。これはつまり,あなたがC言語書いたコードはC言語に限らず,あらゆるライブラリや言語からコール可能である,ということなのです。"
同時にKatz氏は,C言語には "多くの欠陥" があることも認めている。
... 境界チェックがない,メモリ破壊をすぐ起こす,無効なポインタやメモリ/リソースリークの存在,取って付けたような並行性サポート,モジュールがない,ネームスペースもない。エラー処理はいやになるほど面倒で冗長。コールスタックが壊されれば,ありとあらゆるエラーがいとも簡単に発生します。悪意のある入力データによってプロセスを乗っ取られることさえ。クロージャ?とんでもない!
Katz氏のC言語への愛情は,C言語プラグインとErlang VMとの組み合わせに起因する,Couchbaseのパフォーマンス的限界とデバッグ上の問題を打開する必要性から発しているようだ。氏はC++やGo,あるいはDがCの代替になるとは思っていないが,Rustについては,"C言語並のパフォーマンスを持ちながら,Erlangの並列性と堅牢性を安全に利用可能なビルトイン" を実現できたならば,"自分にとって夢の言語" になるかも知れない,と考えている。
Katz氏の記事は,Reddit や Hacker News で大きな議論を巻き起こした。多くの開発者がC言語のメリットに異議を唱えて,他の言語を推奨している。例えばrobinei 氏が問題視するのは,C言語の 文字列操作 と,エラーチェックが不統一である点だ。
私は (C++や他の言語から) C言語に戻って,その爽快なシンプルさを満喫したいといつも思ってるのです。本当にいいものです。
でもそうすると,文字列操作や,やっかいな作業をしなければならなくなる ..
メモリアロケーションを多用する処理では,すべての領域をひとつひとつ,確実に解放しなければならないのが大変です。手の込んだアリーナアロケータツリーとGo風のスライス文字列でこの問題を解決しようと試みていますが,C言語に (ネームスペースを接頭辞にした関数以上の) ろくなシンタックスツールが存在しないせいで,何をするにも必要以上の手間が掛かるのです (その上,すべてのメモリをアリーナに割り当てるのも辛い作業です)。
明示的なエラーチェック (通常は発生しなくても,sqliteのようなライブラリでは 何が 失敗するか分かりませんから) を書けば,ソースファイルは必要な大きさの2倍にもなってしまいます。
エネルギーを消耗するようなことばかりで,ちっとも満足を得ることはできません。
そんなことを暫く続けた後はいつも最初の場所に,大抵はC++に戻ることになります。
madhadron 氏が訴えるのは "もっと現実的なC言語の姿" だ。
- C言語は高速なマシンコードにコンパイル可能です – PDP-11では …
- C言語の標準ライブラリはジョークレベルです。特に文字列操作に関する粗末さは,過去40年間のセキュリティホールに対して,ある部分の責任を負っていると言ってもよいでしょう。
- C言語のツーリングは,SmalltalkやLispなど同時代の言語と比べても,見るべきものがほとんど何もありません。 C言語で使用されるデバッガのほとんどは,コマンドラインの化け物のようなものです。SqueakやAllegro Common Lispなどの標準デバッガと比べてみてください。
- C言語のビルド/デバッグ/実行サイクルが高速だと主張するのも,情けない話です。早く思えるのは,C++にこの分野で問題があるからです。ビルド/デバッグ/実行サイクルが速くする方法を知りたければ,Turbo Pascalを見ればよいでしょう。
- 標準化されたABI経由でC言語がどこからでも呼出可能というのは,Unixの世界だけで通用する話です。残念なことに,現時点ではほぼ事実なのですが,それは他に適当な回避策が存在しないことを理由とする,C言語の偏在性によるものと言ってよいでしょう。
C言語,C++,そしてJava。これらはプログラマにとって,じゃんけんのようなものです。
私は最初,C言語から始めました。ずっと昔の話です。ステートメントや関数を組み合わせるためには,マクロやライブラリがとても便利だと思ったものです。その後でオブジェクトを学び,C++を知りました。
C++はかなり早い時期(cfrontの頃)から始めたのですが,長い間,とても気に入って使っていました。しかし同時に言語としての複雑さや,機能間のとても微妙な相互作用には悩まされました。メモリ管理もにうんざりでした。私はJavaにあこがれました。そして,そのチャンスが来たのです。
私は満足でした。でも言語を学んでいくうちに,何かを失っていることに気付いたのです。オブジェクトはすべてヒープに?まさか?オブジェクトを他のオブジェクトの中に,物理的に埋め込むことができないって?ですが,その他の部分はとても素晴らしいものでしたから,私は気にしないことにしました。
そして今,私は,数GBのメモリを使って,大小合わせて数百万のオブジェクトを管理するシステムをいくつも作るようになりました。オブジェクトごとに発生するオーバーヘッドには耐えがたいものがありますし,GCのチューニングはさながら悪夢です。メモリのサブアロケーション用のスキーマを実装したり,通常のオブジェクト操作とバイト配列にシリアライズされたオブジェクトとを比較するために,マイクロベンチマークを書いたりしています。そしてC++はと言えば,私が苦労した頃よりもはるかに煩雑で,複雑なものになっています。今はC言語を懐かしく思っています。
ですから今の私は,どの言語も好きではありません。
C言語は今日使用するにはあまりにも欠陥が多く,非生産的である,とする人々がいる一方で,限定的ではあるが十分に活用する余地は残っている,という考えの人たちもいる。最高の言語は何かという論争は避けて,それぞれの言語のトレードオフの理解に努め,現在のプロジェクトとスキルにもっとも相応しいと考えられるものを選ぶことが,開発者のコミュニティの選択するべき方法だろう。結局のところ,完璧なプログラム言語など存在しないのだ。