C ++ 17でawaitを使用してコルーチンを受け入れることに反対

最近、標準化委員会の作業に参加しているC ++専門家のグループがロシアを訪問しました。 2月25日、彼らはYandex主催のQ&Aセッションに参加し、C ++ Russia 2016カンファレンスで講演しました。その1人はC ++ 17標準にC#のようなコルーチン(非同期/待機)を含める提案の著者であるGor Nishanovでした。 以前、ゴアはCppCon 2015でレポート「 C ++コルーチン-オーバーヘッドが負の抽象化 」で講演しました 。 非同期コードを構築するこのような機会は魅力的に見えます。レポートのゴアは、コードの量が削減され、「手書き」のステートマシンと比較して速度が向上することを確信して示しています。 さらに、それは次の標準の最大の潜在的な変更の1つであり、注目を集めています。 出版物から判断すると、提案はかなりの承認を受け、委員会は標準に含まれる傾向があります。



その後、前述の提案P0057をダウンロードすることで、コルーチンの提案された実装に厳しい感情的な批判があり、C ++ 17に含めるのではなく、それを延期することを要求するカウンタードキュメント「 コルーチンがTSに属している 」を受け取ったときに非常に驚いた技術仕様の「慣らし」。 私はこれらの異議の支持者ではないことに注意しますが、これらの主張がどのように実証されているか、すべてがそれほど悪いかどうかについて、議論に興味がある人を招待します。 いくつかのコメントを付けて、ドキュメントから切り取った「絞り込み」。



最初に注意を払うこと:対戦相手の1人は、非同期プログラミングの専門家と見なすことができる、著者であり管理者であるBoost.AsioであるChristopher Kohlhoffです。 次に、ドキュメントのシャープで感情的なトーンが目を引きます。 ささいな発言だけでなく、根本的な不一致。 以下にいくつかの引用を示します。



この文は他の言語からコピーしたように見えますが、彼らが犯した間違いからは学びません。 これらのエラーをC ++で盲目的にコピーしないでください。



... C ++ 17にこのような提案を含めたいという欲求は、性急で愚かなものです。



正しく実装された最初の言語の1つになる可能性があることを考えると、最適でない、つまり壊れたアプローチを標準化しようと急いでいることに驚いています。



C ++ 17に「大きなチケット」機能と「クールな」機能を追加したいという欲求を無視する大きな赤い旗が2つあります。




だから、どのような主張が提示されます:



1)最も重要なポイント:awaitキーワードを使用して、中断が発生する非同期呼び出しをマークする必要がある。 このドキュメントの著者は、このモデルを「中断」と呼び、そのような不利な点をリストしています。





著者は、このモデルをいわゆる「サスペンドダウン」モデルと比較しています。これは侵襲的ではなく、Boost.Coroutinesで使用されています。 クリストファー・コールホフによって「再開可能な表現」という委員会にも提案されましたが、C#のような待ち方が優先されました。

このモデルの違いは、awaitという単語で非同期呼び出しをマークする必要がないことです。 「外部からは通常の関数のように見える」エンティティは、たとえばsuspend()と呼ばれます。 呼び出しメソッドを終了せずに内部的にコンテキストを切り替え(Boost.CoroutinesはBoost.Contextを使用)、非同期操作が完了するまで呼び出しスタック全体を「一時停止」します。 同時に、チェーン内の最初の関数は、非同期操作の原因を「認識」することさえできないため、既存のコードを変更する必要はありません。



Gor Nishanovは、このテーマについて次のように回答しました(CppConに関するビデオレポート、YandexでのQ&A):





2)このドキュメントの著者が示していることは次のとおりです。コルーチンを設計するとき、短い応答時間を必要とするプラットフォームの経験とユースケースの重要な部分は無視されました。 たとえば、金融市場向けのシステムが提供されています。 このようなシステムの運用は法律によって規制されており、失敗すると調査と訴追につながる可能性があることが示されています。

このため、思考実験は適切ではなく、コルーチンはそのような領域で事前にテストする必要があります。



3)「世界の衝突」のスタイルにおける興味深い議論は次のとおりです。Linuxは高性能システムの最も一般的なプラットフォームであるため、MSVC / Windowsのコルーチンの試用実装はパフォーマンスをほとんど評価しません。



4)C#awaitスタイルのコルーチンは、主に他の言語から単純に構文をコピーした結果です。 彼らはコピーして運用しました。 同時に、これらの言語のコルーチンのエラーと欠点がコピーされました(C#、Python)。



さらに、コルーチンモデルは主に動的言語から借用されました。 そして、それは最適ではなく、C ++の方がうまくいく可能性が非常に高いです。



5)セキュリティとパフォーマンスのリスク:現在のコルーチン設計では、ジッタ、個々のタスクのリソース不足(飢)、およびDOS攻撃のリスクが増加します。 1つの理由は、コルーチンが混雑するのではなく、協調マルチタスクを使用することです。 したがって、スレッドの数が少ないと、1つのコルーチンが長時間リソースを消費する可能性があり、OSスケジューラーが助けになりません。



正直なところ、この点は私にはいくらか引き出されているように思えました。 いずれの場合でも、個々の実装の詳細を修正でき、モデルに固有の基本的な欠陥は表示されません。



6)正当性のリスク:非同期操作の完了後、コルーチンは別のスレッドで続行できます。 著者は、この振る舞いは受け入れられると信じていますが、デフォルトではないはずです。



同時に、C#ではこの問題は完全に解決されます。 操作がUIスレッドから開始される場合、継続は常にUIスレッドでも呼び出されます。



7)リスクは、待機(サスペンドアップ)モデルが受け入れられると、標準(Boost.Corountinesでモデル化)にサスペンドダウンモデルを含めることが複雑になることです。 すでに存在する機能に時間を費やすように標準化委員会を説得することは難しくなります。



提案された待機コルーチンがライブラリレベルでのみ実装された場合、代替オプションの操作と研究の余地が残されます。 しかし、現在の形態では、後戻りはできないかもしれません。



申し出





1)C ++ 17にコルーチンを含めることを延期し、今のところ「実行」の技術仕様に含めること。



2)サスペンドダウンモデルの作業を継続すると、将来の標準である「サスペンドアップコルーチン」および「サスペンドダウンコルーチン」のコルーチンに関する2つの提案を策定することができます。



3)Gor NishanovがMicrosoftでVisual Studioコンパイラを実験および改良できたため、コルーチンの現在の提案は大いに利益を得ました。 したがって、代替コルーチンモデルの作成者は、GCCおよびClangの開発者と協力して、負荷の高いLinuxシステムを完成させて実験することを期待しています。



おわりに





結論として、著者は2つの「大きな赤い旗」があることに言及しています。



1)さまざまな理由で、負荷の高いシステムでコルーチンを使用した経験が豊富な委員会のメンバーは、ほとんど影響を与えません。



2)現在、技術仕様にはいくつかの提案があります:並列性、同時実行性、ネットワーキング、および潜在的に中断アップコルーチンと中断ダウンコルーチン。単一で一貫したモデルまたは少なくとも思慮深い相互作用が必要です。



したがって、時間を必要とし、コルーチンを急ぐことは価値がありません。



あなたの意見は? これらの欠点はどれほど重要ですか?

また、後で2つの品種を一度に標準に含めるためにコルーチンを先送りする価値はありますか?



UPD :コメントでは、 Mikanorは2013 Meeting C ++ブログの記事「 再開可能な関数-非同期と 待機 」へのリンクを提供しています。 それは、待ち合わせを伴うコルーチンの元のアイデアと利点をほとんど説明しています。

Habréには、この記事のタングロとディスカッションの翻訳がありました。



UPD2 :この記事は、ドキュメント「コルーチンはTSに属している」の完全な翻訳ではなく、コルーチンの待機中の別の視点(特にサスペンドアップとサスペンドダウン)に注意を引くように設計されたダイジェストです。 各ドキュメントの詳細と詳細な説明は、 ソースドキュメントで確認できます



All Articles