xref: /aosp_15_r20/external/libchrome/base/task_scheduler/service_thread.cc (revision 635a864187cb8b6c713ff48b7e790a6b21769273)
1*635a8641SAndroid Build Coastguard Worker // Copyright 2018 The Chromium Authors. All rights reserved.
2*635a8641SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*635a8641SAndroid Build Coastguard Worker // found in the LICENSE file.
4*635a8641SAndroid Build Coastguard Worker 
5*635a8641SAndroid Build Coastguard Worker #include "base/task_scheduler/service_thread.h"
6*635a8641SAndroid Build Coastguard Worker 
7*635a8641SAndroid Build Coastguard Worker #include "base/bind.h"
8*635a8641SAndroid Build Coastguard Worker #include "base/bind_helpers.h"
9*635a8641SAndroid Build Coastguard Worker #include "base/debug/alias.h"
10*635a8641SAndroid Build Coastguard Worker #include "base/rand_util.h"
11*635a8641SAndroid Build Coastguard Worker #include "base/stl_util.h"
12*635a8641SAndroid Build Coastguard Worker #include "base/task_scheduler/post_task.h"
13*635a8641SAndroid Build Coastguard Worker #include "base/task_scheduler/task_scheduler.h"
14*635a8641SAndroid Build Coastguard Worker #include "base/task_scheduler/task_tracker.h"
15*635a8641SAndroid Build Coastguard Worker #include "base/task_scheduler/task_traits.h"
16*635a8641SAndroid Build Coastguard Worker #include "build/build_config.h"
17*635a8641SAndroid Build Coastguard Worker 
18*635a8641SAndroid Build Coastguard Worker namespace base {
19*635a8641SAndroid Build Coastguard Worker namespace internal {
20*635a8641SAndroid Build Coastguard Worker 
21*635a8641SAndroid Build Coastguard Worker namespace {
22*635a8641SAndroid Build Coastguard Worker 
23*635a8641SAndroid Build Coastguard Worker TimeDelta g_heartbeat_for_testing = TimeDelta();
24*635a8641SAndroid Build Coastguard Worker 
25*635a8641SAndroid Build Coastguard Worker }  // namespace
26*635a8641SAndroid Build Coastguard Worker 
ServiceThread(const TaskTracker * task_tracker)27*635a8641SAndroid Build Coastguard Worker ServiceThread::ServiceThread(const TaskTracker* task_tracker)
28*635a8641SAndroid Build Coastguard Worker     : Thread("TaskSchedulerServiceThread"), task_tracker_(task_tracker) {}
29*635a8641SAndroid Build Coastguard Worker 
30*635a8641SAndroid Build Coastguard Worker // static
SetHeartbeatIntervalForTesting(TimeDelta heartbeat)31*635a8641SAndroid Build Coastguard Worker void ServiceThread::SetHeartbeatIntervalForTesting(TimeDelta heartbeat) {
32*635a8641SAndroid Build Coastguard Worker   g_heartbeat_for_testing = heartbeat;
33*635a8641SAndroid Build Coastguard Worker }
34*635a8641SAndroid Build Coastguard Worker 
Init()35*635a8641SAndroid Build Coastguard Worker void ServiceThread::Init() {
36*635a8641SAndroid Build Coastguard Worker   // In unit tests we sometimes do not have a fully functional TaskScheduler
37*635a8641SAndroid Build Coastguard Worker   // environment, do not perform the heartbeat report in that case since it
38*635a8641SAndroid Build Coastguard Worker   // relies on such an environment.
39*635a8641SAndroid Build Coastguard Worker   if (task_tracker_ && TaskScheduler::GetInstance()) {
40*635a8641SAndroid Build Coastguard Worker // Seemingly causing power regression on Android, disable to see if truly at
41*635a8641SAndroid Build Coastguard Worker // fault : https://crbug.com/848255
42*635a8641SAndroid Build Coastguard Worker #if !defined(OS_ANDROID)
43*635a8641SAndroid Build Coastguard Worker     // Compute the histogram every hour (with a slight offset to drift if that
44*635a8641SAndroid Build Coastguard Worker     // hour tick happens to line up with specific events). Once per hour per
45*635a8641SAndroid Build Coastguard Worker     // user was deemed sufficient to gather a reliable metric.
46*635a8641SAndroid Build Coastguard Worker     constexpr TimeDelta kHeartbeat = TimeDelta::FromMinutes(59);
47*635a8641SAndroid Build Coastguard Worker 
48*635a8641SAndroid Build Coastguard Worker     heartbeat_latency_timer_.Start(
49*635a8641SAndroid Build Coastguard Worker         FROM_HERE,
50*635a8641SAndroid Build Coastguard Worker         g_heartbeat_for_testing.is_zero() ? kHeartbeat
51*635a8641SAndroid Build Coastguard Worker                                           : g_heartbeat_for_testing,
52*635a8641SAndroid Build Coastguard Worker         BindRepeating(&ServiceThread::PerformHeartbeatLatencyReport,
53*635a8641SAndroid Build Coastguard Worker                       Unretained(this)));
54*635a8641SAndroid Build Coastguard Worker #endif
55*635a8641SAndroid Build Coastguard Worker   }
56*635a8641SAndroid Build Coastguard Worker }
57*635a8641SAndroid Build Coastguard Worker 
Run(RunLoop * run_loop)58*635a8641SAndroid Build Coastguard Worker NOINLINE void ServiceThread::Run(RunLoop* run_loop) {
59*635a8641SAndroid Build Coastguard Worker   const int line_number = __LINE__;
60*635a8641SAndroid Build Coastguard Worker   Thread::Run(run_loop);
61*635a8641SAndroid Build Coastguard Worker   base::debug::Alias(&line_number);
62*635a8641SAndroid Build Coastguard Worker }
63*635a8641SAndroid Build Coastguard Worker 
PerformHeartbeatLatencyReport() const64*635a8641SAndroid Build Coastguard Worker void ServiceThread::PerformHeartbeatLatencyReport() const {
65*635a8641SAndroid Build Coastguard Worker   static constexpr TaskTraits kReportedTraits[] = {
66*635a8641SAndroid Build Coastguard Worker       {TaskPriority::BACKGROUND},    {TaskPriority::BACKGROUND, MayBlock()},
67*635a8641SAndroid Build Coastguard Worker       {TaskPriority::USER_VISIBLE},  {TaskPriority::USER_VISIBLE, MayBlock()},
68*635a8641SAndroid Build Coastguard Worker       {TaskPriority::USER_BLOCKING}, {TaskPriority::USER_BLOCKING, MayBlock()}};
69*635a8641SAndroid Build Coastguard Worker 
70*635a8641SAndroid Build Coastguard Worker   // Only record latency for one set of TaskTraits per report to avoid bias in
71*635a8641SAndroid Build Coastguard Worker   // the order in which tasks are posted (should we record all at once) as well
72*635a8641SAndroid Build Coastguard Worker   // as to avoid spinning up many worker threads to process this report if the
73*635a8641SAndroid Build Coastguard Worker   // scheduler is currently idle (each pool keeps at least one idle thread so a
74*635a8641SAndroid Build Coastguard Worker   // single task isn't an issue).
75*635a8641SAndroid Build Coastguard Worker 
76*635a8641SAndroid Build Coastguard Worker   // Invoke RandInt() out-of-line to ensure it's obtained before
77*635a8641SAndroid Build Coastguard Worker   // TimeTicks::Now().
78*635a8641SAndroid Build Coastguard Worker   const TaskTraits& profiled_traits =
79*635a8641SAndroid Build Coastguard Worker       kReportedTraits[RandInt(0, base::size(kReportedTraits) - 1)];
80*635a8641SAndroid Build Coastguard Worker 
81*635a8641SAndroid Build Coastguard Worker   // Post through the static API to time the full stack. Use a new Now() for
82*635a8641SAndroid Build Coastguard Worker   // every set of traits in case PostTaskWithTraits() itself is slow.
83*635a8641SAndroid Build Coastguard Worker   // Bonus: this appraoch also includes the overhead of Bind() in the reported
84*635a8641SAndroid Build Coastguard Worker   // latency).
85*635a8641SAndroid Build Coastguard Worker   base::PostTaskWithTraits(
86*635a8641SAndroid Build Coastguard Worker       FROM_HERE, profiled_traits,
87*635a8641SAndroid Build Coastguard Worker       BindOnce(&TaskTracker::RecordLatencyHistogram, Unretained(task_tracker_),
88*635a8641SAndroid Build Coastguard Worker                TaskTracker::LatencyHistogramType::HEARTBEAT_LATENCY,
89*635a8641SAndroid Build Coastguard Worker                profiled_traits, TimeTicks::Now()));
90*635a8641SAndroid Build Coastguard Worker }
91*635a8641SAndroid Build Coastguard Worker 
92*635a8641SAndroid Build Coastguard Worker }  // namespace internal
93*635a8641SAndroid Build Coastguard Worker }  // namespace base
94