mirror of
https://github.com/klzgrad/naiveproxy.git
synced 2024-12-01 09:46:09 +03:00
103 lines
3.7 KiB
C++
103 lines
3.7 KiB
C++
// Copyright 2018 The Chromium Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
#include "base/task/task_scheduler/service_thread.h"
|
|
|
|
#include "base/bind.h"
|
|
#include "base/bind_helpers.h"
|
|
#include "base/debug/alias.h"
|
|
#include "base/rand_util.h"
|
|
#include "base/stl_util.h"
|
|
#include "base/task/post_task.h"
|
|
#include "base/task/task_scheduler/task_scheduler.h"
|
|
#include "base/task/task_scheduler/task_tracker.h"
|
|
#include "base/task/task_traits.h"
|
|
|
|
namespace base {
|
|
namespace internal {
|
|
|
|
namespace {
|
|
|
|
TimeDelta g_heartbeat_for_testing = TimeDelta();
|
|
|
|
} // namespace
|
|
|
|
ServiceThread::ServiceThread(const TaskTracker* task_tracker,
|
|
RepeatingClosure report_heartbeat_metrics_callback)
|
|
: Thread("TaskSchedulerServiceThread"),
|
|
task_tracker_(task_tracker),
|
|
report_heartbeat_metrics_callback_(
|
|
std::move(report_heartbeat_metrics_callback)) {}
|
|
|
|
ServiceThread::~ServiceThread() = default;
|
|
|
|
// static
|
|
void ServiceThread::SetHeartbeatIntervalForTesting(TimeDelta heartbeat) {
|
|
g_heartbeat_for_testing = heartbeat;
|
|
}
|
|
|
|
void ServiceThread::Init() {
|
|
// In unit tests we sometimes do not have a fully functional TaskScheduler
|
|
// environment, do not perform the heartbeat report in that case since it
|
|
// relies on such an environment.
|
|
if (TaskScheduler::GetInstance()) {
|
|
// Compute the histogram every hour (with a slight offset to drift if that
|
|
// hour tick happens to line up with specific events). Once per hour per
|
|
// user was deemed sufficient to gather a reliable metric.
|
|
constexpr TimeDelta kHeartbeat = TimeDelta::FromMinutes(59);
|
|
|
|
heartbeat_metrics_timer_.Start(
|
|
FROM_HERE,
|
|
g_heartbeat_for_testing.is_zero() ? kHeartbeat
|
|
: g_heartbeat_for_testing,
|
|
BindRepeating(&ServiceThread::ReportHeartbeatMetrics,
|
|
Unretained(this)));
|
|
}
|
|
}
|
|
|
|
NOINLINE void ServiceThread::Run(RunLoop* run_loop) {
|
|
const int line_number = __LINE__;
|
|
Thread::Run(run_loop);
|
|
base::debug::Alias(&line_number);
|
|
}
|
|
|
|
void ServiceThread::ReportHeartbeatMetrics() const {
|
|
report_heartbeat_metrics_callback_.Run();
|
|
PerformHeartbeatLatencyReport();
|
|
}
|
|
|
|
void ServiceThread::PerformHeartbeatLatencyReport() const {
|
|
if (!task_tracker_)
|
|
return;
|
|
|
|
static constexpr TaskTraits kReportedTraits[] = {
|
|
{TaskPriority::BEST_EFFORT}, {TaskPriority::BEST_EFFORT, MayBlock()},
|
|
{TaskPriority::USER_VISIBLE}, {TaskPriority::USER_VISIBLE, MayBlock()},
|
|
{TaskPriority::USER_BLOCKING}, {TaskPriority::USER_BLOCKING, MayBlock()}};
|
|
|
|
// Only record latency for one set of TaskTraits per report to avoid bias in
|
|
// the order in which tasks are posted (should we record all at once) as well
|
|
// as to avoid spinning up many worker threads to process this report if the
|
|
// scheduler is currently idle (each pool keeps at least one idle thread so a
|
|
// single task isn't an issue).
|
|
|
|
// Invoke RandInt() out-of-line to ensure it's obtained before
|
|
// TimeTicks::Now().
|
|
const TaskTraits& profiled_traits =
|
|
kReportedTraits[RandInt(0, base::size(kReportedTraits) - 1)];
|
|
|
|
// Post through the static API to time the full stack. Use a new Now() for
|
|
// every set of traits in case PostTaskWithTraits() itself is slow.
|
|
// Bonus: this appraoch also includes the overhead of Bind() in the reported
|
|
// latency).
|
|
base::PostTaskWithTraits(
|
|
FROM_HERE, profiled_traits,
|
|
BindOnce(&TaskTracker::RecordLatencyHistogram, Unretained(task_tracker_),
|
|
TaskTracker::LatencyHistogramType::HEARTBEAT_LATENCY,
|
|
profiled_traits, TimeTicks::Now()));
|
|
}
|
|
|
|
} // namespace internal
|
|
} // namespace base
|