標準ライブラリが死んだ日

プラハでは、C++ 委員会が ABI を壊すかどうかについて一連の投票を行い、壊さないことを決定しました。
拍手はありませんでした。
しかし、私たちが何をしたか、そしてそれがもたらす可能性のある結果を完全に理解しているかどうかはわかりません.

どれも良い結果にはならないと私は信じています.

ABI とは

ABI は、レイアウト、呼び出し規則、マングリングの両方の観点から、プログラムがどのようにシリアル化されるかについてライブラリが共有する理解です。バージョン管理されていないにもかかわらず、まさにバイナリ プロトコルです。
これは少し複雑かもしれないので、ABI の安定性に必要なものを列挙した方がよいと思います:

次のいずれかを行うと、コンパイル済みライブラリの新しいバージョンでシンボルを使用できなくなります:

  • 既存のクラスにデータ メンバーを追加する
  • テンプレートの引数を変更する、関数テンプレートを非テンプレートに、またはその逆に変換する、またはテンプレートを可変個引数にする
  • 以前はインライン化されていなかったものをインライン化する
  • デフォルトの引数を関数に追加する
  • 仮想機能を追加する

他にもたくさんありますが、これらは通常、委員会が遭遇するものであり、その場で提案を殺す傾向があるものです。また、ソースブレークでもある ABI ブレーク操作 (関数の削除または変更) を省略しました。実際には、互換性を損なわない便利な変更です。
例:std::string string_view を持っています 火で殺したい変換演算子、それはソース ブレークではない ABI ブレーク、またはほとんど無音のものである可能性があります。

なぜ ABI を壊したいのか

ABI ブレークによって有効になる実装品質の変更がいくつかあります

  • 連想コンテナを (はるかに) 高速化する
  • std::regex を作る より高速です (現在、std::regex を使用するよりも、正規表現を実行するために PHP を起動する方が高速です)
  • string の微調整 、 vector 、およびその他のコンテナ レイアウト
  • 適合性の向上:一部の実装は、安定性のために意図的に適合していません

さらに重要なことに、ABI を壊す設計変更があります。ここ数年で、次の機能で ABI の問題が発生しました。これは完全なリストではありません。

  • scoped_lock lock_guard を変更して ABI を壊さないように追加されました
  • int128_t intmax_t を変更したため、標準化されたことはありません ABIブレイクです。私に言わせれば intmax_t 廃止する必要があります。
  • unique_ptr ポインターと比較して、オーバーヘッドをゼロにするために必要な言語の変更に対応できます
  • error_code への多くの変更 ABI を壊してしまうという理由で却下された
  • status_code ABI に関する懸念の提起
  • recursive_directory_iterator にフィルターを追加する提案 ABI 違反のため拒否されました
  • <cstring>を最大限に活用するための提案 constexpr (strlen を含む) ) は、ABI ブレークになるため、おそらく終了します。
  • regex への UTF-8 サポートの追加 は ABI ブレークです
  • realloc のサポートの追加 または、割り当てられたサイズを返すことは、ポリモーフィック アロケーターの ABI ブレークです
  • ポリモーフィック クラスでデストラクタを暗黙的に仮想化する
  • push_back の戻り値の型は、ABI ブレークで改善される可能性があります
  • 実際、push_back の両方が本当に必要でしたか? と emplace_back ?
  • shared_ptr を改善すると ABI が壊れる
  • [[no_unique_address]] ABI をまったく気にしなければ、コンパイラによって推論される可能性があります

リストは続きます。WG21 は、これらのリストを維持するために、より良い仕事をする必要があると思います。私がいる部屋で誰かが「ABI ブレイク」と言うたびに注意する必要があります。

他に何を変更したいですか?

知らない。わからないことはわかりません。推測する必要があるとしたら?

  • C++23 の時代では、標準ライブラリのモジュール化は ABI の問題に直面するでしょう。つまり、エクスポートされていないすべてのシンボルは、ABI を壊さないようにグローバル モジュール フラグメントに残す必要があり、モジュールのポイントを少し無効にします。
  • 実装の品質の問題として例外のコストを大幅に削減できると信じている人が多いようですが、それには ABI を破る必要があるかもしれません。
  • コルーチンをさらに改善すると ABI の問題が発生する可能性があり、コルーチンは大幅に改善される可能性があります。
  • 移転には、ABI の問題もあって、明示的なオプトインが必要です。
  • トゥームストーンの提案は、確実に ABI の懸念を引き起こすでしょう。

プラハでの ABI ディスカッション

プラハでは、ABI の議論が一連の世論調査をリードしていますが、残念ながら、それは茶葉と同じくらい明らかであり、そのため、あなたがグラス半分一杯かグラス半分空のタイプの人かによって、これらの結果の解釈が異なるかもしれません.

基本的な方向性は次のとおりです:

  • WG21 は 23 年の ABI 中断で賛成ではありません
  • WG21 は、C++ の将来のバージョンでの ABI の中断を支持しています
  • WG21 は、ABI の中断を必要とする提案を検討するために時間をかけます
  • WG21 が永遠の安定を約束するわけではありません
  • WG21 は、安定性よりもパフォーマンスを優先し続けたいと考えています。

これらすべての世論調査では、明らかに過半数が一致していますが、コンセンサスは得られていません。

茶葉を読む

C++ 何か何か

これらの投票の明らかな欠陥は、いつを明確にしていないことです ABIを壊したいでしょう。
C++23?いいえ、これは決定的なノーです。
C++26?決定的にそれに投票するつもりだった人もいれば、おそらく C++41 で ABI を壊すことに投票した人もいれば、引退するか、現在のプロジェクトに対処する必要がなくなったら ABI を壊すことに投票した人もいます。知る由もありません。正確な調査では、「C++ SOMETHING」が言及されていました。

ABI を今破ることができなくても、後で破られる可能性があると信じる理由はありません。安定性を必要とする人々は、標準からかなり遅れて何年も遅れています。したがって、今 ABI を破らなければ、人々は約束もされていない ABI に 10 年以上、おそらく 2 年以上も依存してきました。私たちがこの会話を行い、ABI を壊さないことに投票したという単純な事実は、エコシステムが急速に硬直化していることを示しています。日を追うごとに問題が少しずつ増えています。より悪く、より高価です。

世論調査が 3 年後に再び実施された場合、結果が変わるとは確信していません。気候変動のようなものです。誰もが、この問題に投資することに同意しますいつか .2070 年にディーゼル車を禁止しましょう。

今後 5 年間に予定されていないことは、まったく意味がありません。

ABI に違反する提案を検討しています

WG21 は、ABI の違反提案により多くの時間を割くことを投票しました。

これにはいくつかの意味があります:

  • 委員会の最も忙しい部屋の 1 つに時間を費やすことで、前進する可能性が高い提案に時間を割くことができますが、最終的には提案を却下することになります
  • 壊れない代替手段を見つける (詳細は後述)
  • 部分的な ABI ブレークの操作 (詳細は後述)

ABI よりもパフォーマンスを優先する

これは、5 歳児にキャンディーが欲しいかどうかを尋ねるようなものでした.そこで、パフォーマンスを気にすることに投票しました.しかし、驚くべきことに、多くの人が反対票を投じました.

私の解釈では、委員会はそのケーキを欲しがり、それも食べます.これは不可能です。

パフォーマンス
ABI の安定性
変化する能力

2 つ選ぶことができます。賢明に選択してください。#cppprg

— ブライス・アデルスタイン・レルバッハ 🇺🇦 (@blelbach) 2020年2月16日

最終的に、安定性と ABI は、十分な期間が与えられると、互いに衝突します。
ただし、この投票は重要でした:基本的な質問に触れています:

C++ とは何ですか? 標準ライブラリとは何ですか?

宣伝されている言葉は、「パフォーマンス」、「ゼロコストの抽象化」、「使用しないものにはお金を払わない」です。ABI の安定性は、これらすべてに直接反します。

広範囲にわたる結果

23 で ABI を破らなかったことは、委員会がこれまでに犯した最悪の過ちであると私は強く信じています。
とにかく、その決定の結果として何が起こるかは次のとおりです。

教育の悪夢

非常に明確にしましょう。 ABI に依存するプログラムは、おそらくどこかで ODR に違反しており、たまたま機能する互換性のないフラグを使用している可能性があります。

新しいプログラムはソースからビルドする必要があります。ランダムな場所からフェッチして急いでつなぎ合わせたライブラリのコレクションではなく、ソース ファイルのコンパイルを中心に設計されたビルド ツールを使用する必要があります。

はい、ソースからのビルドは達成が難しいものです。成熟したエコシステムとシームレスなコンパイラの更新を奨励する必要があります。人々が新しいコンパイラ機能の恩恵を受ける方法を、数十年ではなく数か月で見つける必要があります。スケーラブルで再現可能なビルド。ソース ライブラリを簡単にインポートできるようにし、依存関係の活発なエコシステムを促進する必要があります。

ABI を壊さないことで、委員会は、あなたの不正なプログラムを永久にサポートすることを明確に述べています。

これは大きな後退です。インセンティブがない場合、どのように優れた慣行を教え、システムの衛生状態を構築すればよいのでしょうか?

標準ライブラリへの関心の喪失

ABI を壊したくないという私たちの不本意による推定パフォーマンス損失は、5-10% と推定されています この数は時間の経過とともに増加します。大局的に見ると

  • ビッグ テック企業の場合は、新しいデータ センターを購入するか、チームにお金を払ってライブラリを維持することができます
  • あなたが組み込み開発者の場合、5% の違いでソフトウェアが実行されるか、数百万ドルもかかる高価なチップを購入する必要があるか
  • あなたがゲーム会社の場合、ゲームが素晴らしいか、ユーザーが VR ヘッドセットで嘔吐するかの違いかもしれません
  • 取引をしている場合、取引が成功するかどうかの違いかもしれません。

いずれにせよ「C++を使えばいいのに!」の違いだと思います。 「標準ライブラリを使ったほうがいい」「標準ライブラリを使わないほうがいいかもしれない」、「C++を使わないほうがいいかもしれない」まで。たぶん、.net、julia、rust を使用する必要がありますか?」.もちろん、その決定には他にも多くの要因がありますが、しばらくの間、それが起こっているのを見てきました.

多くのゲーム開発者は、標準ライブラリに懐疑的であることで有名です。たとえば、EASTL.Facebook には愚かさがあり、Google には Abseil があります。

これは雪だるま式になる可能性があります。標準ライブラリを使用しない人は、それを改善することに関心がありません。標準ライブラリを存続させるのはパフォーマンスです。パフォーマンスがなければ、それに注がれるエネルギーははるかに少なくなります。

それらは一般的で、すぐに入手できますか? (これにはある程度の価値があります。)

ABI にコミットすることは、標準ライブラリがマクドナルドになることを目指していることを認めるようなものです。標準ライブラリはどこにでもあり、一貫性があり、技術的に問題を解決します。

— タイタス・ウィンターズ (@TitusWinters) 2020 年 2 月 3 日

委員会は ABI を破る提案にどのように対処できますか?

ABI を破ることができないという苦痛を和らげるために、いくつかのことが提案されています:

新しい名前の追加

unordered_map を修正できない場合、これは明らかな解決策です。 、おそらく std::fast_map を追加できます ?そうしない理由がいくつかあります。標準に型を追加することは、教育と認識のオーバーヘッドの点で費用がかかり、使用するコンテナを教えようとする何千もの記事が避けられません。どのstd::scoped_lock または std::lock_guard 使うべきですか?何も思いつきません。毎回見なければなりません。適切な名前には限りがあるという問題もあります。コンテナをあるタイプから次のタイプに絶えず変換する必要があるため、ランタイム コストが追加されます。また、オーバーロード セットを管理できなくするなどです。

皮肉なことに、この解決策を支持する人々と、C++ は複雑すぎると考えている人々の間には、多くの重複があります。重複した型を追加しても、C++ は単純になりません。

ああ、この提案を受け入れることもできたはずです

一部の実装者は、ABI 違反であるとして却下されたいくつかの提案は実際にはそうではなかった、または非 ABI 違反ソリューションをハックすることができたと主張しています。おそらく、ABI レビュー グループ (ARG) がこの点で役立つはずですが、おそらく別の名前を使用することをお勧めします.

部分的な ABI の中断

すべてのプログラムの ABI を一度に変更するのではなく、特定のタイプまたは機能の ABI を壊すという考え方です。 .委員会は、std::string のレイアウトを変更することで、C++11 でそれを試みました。 、そしてそれは悪かった.とても悪いことは、二度と ABI を壊すことに対する議論として使用されます.

もう 1 レベルの間接化

一部の ABI の問題に対する 1 つの解決策は、型のレイアウトがそのポインターのみになるように、ポインターを介して型のデータにアクセスすることです。これは、ABI の理由で Qt で広く使用されている PIMPL イディオムにほぼ対応しています。データ メンバーに適用されますが、仮想メンバーに関する制約は緩和されません。

さらに重要なことに、ABI 境界にある可能性のあるすべてのものにポインターの間接化とヒープ割り当てを追加することについて話している.STL の場合、共有語彙のコレクションであるため、ほとんどすべてが ABI 境界にあるように設計されているタイプしてください。

その費用は莫大なものになるでしょう。

その設計空間にはいくつかの提案があるかもしれません.特に、言語機能にすることを検討しているいくつかの提案があります.おそらく、パフォーマンスまたは安定性のどちらかを選択できます.

皮肉なことに、標準型を PIMPL 型にすると… ABI が壊れてしまいます。

3 年に 1 回コードを再構築する

ちょっと考えただけです。

さらに、あなたの提案は破棄されなければならないと思います.

逆説的に言えば、C++ はかつてないほど生き生きとしています。プラハでは、250 人が次のような多くのことに取り組みました:

  • 数値
  • 線形代数
  • オーディオ
  • ユニコード
  • 非同期 I/O
  • グラフィック

これらの提案はすべて、今日の標準のほとんどよりも必然的に意見が分かれているという共通点があります。これらの提案は、絶え間なく進化している活発な研究分野を標準化しようとしています。

特に、多くの Unicode アルゴリズムは長期にわたって安定していません。

次に、ネットワーキングという巨大な醜いワームがあります。セキュリティに影響するものを修正することなく標準に入れるのは、非常に無責任です。

C++ が安定していると判断したため、これらの提案はすべて破棄する必要があります。火で、殺されたくない。しかし、そうする必要があります。おそらくそうではないでしょう。

最良の結果は、間違いを犯さず、特定の C++ バージョンで最新技術を標準化し、ゆっくりと衰退させ、修正できないようにすることです (ネットワーク TS の場合、私たちは何も変えたくないので、10 年前に最先端だったものを標準化することを検討していますが、これを劇的に改善できることがわかっています.この話は別の機会に.)

しかしもちろん、私たちは非常に多くの過ちを犯します。

最終的には、すべての決定を変更したくなるでしょう。ツールとプロセスの両方で、エコシステムを変更する能力を構築します。 https://t.co/uo5Ir1MzCY

— ハイラム・ライト (@hyrumwright) 2020 年 2 月 16 日

間違いの中には、その時点で正しいトレードオフとして良心的に犯されるものもあれば、何年も隠されたままであるものもあります。

時は流れますが、標準ライブラリは静止しています。トレードオフは後悔になり、後悔はボトルネックになります。

多くの間違いは API に焼き付けられているため修正できず、API の変更は単純に不可能であるという共通の理解があります。しかし、多くの間違いは修正できます。

C++ は 40 年後も存続します。予測不可能な時期に予測不可能な方法で物事を変更する必要があることを認識しない場合、唯一の勝利の手段はプレイしないことです。

標準の連想コンテナが 10 年以上関連性を持たなかったことは明らかですが、なぜより大きな提案が成功すると考えるのでしょうか?

あなたの提案は破棄されなければなりません。私の提案も破棄されなければなりません。

委員会は ABI を破ることさえできるでしょうか?

多くの人は、実装者が単に委員会を無視するため、委員会は単にその決定を下すことができなかったと信じています.その全体はちょっとした腕相撲であり、委員会は行動しませんでした.

ただし、実際には、実装者にはユーザーがいて、最終的にはユーザーにどのようなトレードオフが強制されるかを認識しなければならないのはユーザーです。

多くの人は、選択ではなく偶然に ABI に依存しています。多くの人が安定性に依存しています。率直に言って、安定性に依存したくない人はいませんか?しかし、すべてのことと同様に、安定性には代償が伴い、C++ エコシステム全体がその代償を払っています。