Chromium Chronicle #1: タスク スケジューリングのベスト プラクティス

Chrome チームは、毎月お届けする Chromium Chronicle を 特に Chromium デベロッパー、 できます。

Chromium Chronicle では、主に技術知識の普及に重点を置いています Chrome を作成、ビルド、テストするためのベスト プラクティスを確認します。計画では コードなど、Chromium デベロッパーにとって関連性が高く有用なトピックを 健康、便利なツール、単体テスト、ユーザー補助など、多岐にわたります。各記事 Chrome のエンジニアが記述、編集します。

Google は、この新しいシリーズを楽しみにしています。皆様にもぜひ活用していただきたいと考えています。準備はできましたか? 最初のエピソードをぜひご覧ください。

タスク スケジューリングのベスト プラクティス

エピソード 1: Gabriel Charette、メキシコシティ、モントリオール(2019 年 4 月)
前のエピソード

プロセス内の非同期実行を必要とする Chrome コードは通常、タスクをポストする 生成できます。シーケンスは Chrome が管理する「仮想スレッド」かつ 独自のスレッドを作成することをおすすめします。オブジェクトは どのシーケンスに 投稿すべきか分からないでしょうか

すべきでないこと

古いパラダイムでは、作成者から SequencedTaskRunner を受け取ります。

Foo::Foo(scoped_refptr backend_task_runner)
    : backend_task_runner_(std::move(backend_task_runner)) {}
すべきこと

推奨されるパラダイムは、独立した SequencedTaskRunner を作成することです。

Foo::Foo()
    : backend_task_runner_(
          base::CreateSequencedTaskRunnerWithTraits({
              base::MayBlock(), base::TaskPriority::BEST_EFFORT})) {}

すべての情報がローカルなため、読み書きが簡単です。 無関係なタスクに相互依存関係が生じるリスクがない。

このパラダイムはテストに関しても優れています。ML モデルに 手動でタスクランナーを実行する場合、テストでは制御されたタスク環境をインスタンス化できる Foo のタスクを管理するには、次のようにします。

class FooTest : public testing::Test {
 public
  (...)
 protected:
  base::test::TaskEnvironment task_environment_;
  Foo foo_;
};

TaskEnvironment を最初に固定することで、自然に確実に Foo の存続期間を通じてタスク環境を管理します。TaskEnvironment Foo の作成リクエストをキャプチャして SequencedTaskRunner と 各 FooTest でそのタスクを管理します。

非同期実行の結果をテストするには、 RunLoop::Run()+QuitClosure() パラダイム:

TEST_F(FooTest, TestAsyncWork) {
  RunLoop run_loop;
  foo_.BeginAsyncWork(run_loop.QuitClosure());
  run_loop.Run();
  EXPECT_TRUE(foo_.work_done());
}

これは RunUntilIdle() よりも優先されますが、非同期関数の場合は不安定な状態になる ワークロードに TaskEnvironment のスコープ外のタスクが含まれる 例:RunUntilIdle() は慎重に使用してください。

もっと詳しくお知りになりたい場合スレッドとタスクに関するドキュメントを読む または、TaskEnvironment への移行にご参加ください。