#include "cc/metrics/latency_ukm_reporter.h"
#include <climits>
#include <memory>
#include <utility>
#include "base/rand_util.h"
#include "cc/metrics/compositor_frame_reporter.h"
#include "cc/metrics/ukm_manager.h"
#include "services/metrics/public/cpp/ukm_recorder.h"
namespace cc {
class LatencyUkmReporter::SamplingController {
public:
SamplingController() = default;
~SamplingController() = default;
bool ShouldRecordNextEvent() {
bool should_record = false;
if (!frames_to_next_event_) {
should_record = true;
frames_to_next_event_ = SampleFramesToNextEvent();
}
DCHECK_GT(frames_to_next_event_, 0);
--frames_to_next_event_;
return should_record;
}
private:
const double kSampleDecayRate = 1.0;
const double kSampleRateMultiplier = 2.0;
int SampleFramesToNextEvent() {
double float_sample = 0.0;
do {
float_sample = -(kSampleRateMultiplier *
std::exp(samples_so_far_ * kSampleDecayRate) *
std::log(1.0 - base::RandDouble()));
} while (float_sample == 0.0);
samples_so_far_++;
int integer_sample =
std::isnan(float_sample)
? INT_MAX
: base::saturated_cast<int>(std::ceil(float_sample));
return integer_sample;
}
int samples_so_far_ = 0;
int frames_to_next_event_ = 0;
};
LatencyUkmReporter::LatencyUkmReporter()
: compositor_latency_sampling_controller_(
std::make_unique<SamplingController>()),
event_latency_sampling_controller_(
std::make_unique<SamplingController>()) {}
LatencyUkmReporter::~LatencyUkmReporter() = default;
void LatencyUkmReporter::ReportCompositorLatencyUkm(
const CompositorFrameReporter::FrameReportTypes& report_types,
const std::vector<CompositorFrameReporter::StageData>& stage_history,
const ActiveTrackers& active_trackers,
const CompositorFrameReporter::ProcessedBlinkBreakdown&
processed_blink_breakdown,
const CompositorFrameReporter::ProcessedVizBreakdown&
processed_viz_breakdown,
const CompositorFrameReporter::ProcessedTreesInVizBreakdown&
processed_trees_in_viz_breakdown) {
if (ukm_manager_ &&
compositor_latency_sampling_controller_->ShouldRecordNextEvent()) {
ukm_manager_->RecordCompositorLatencyUKM(
report_types, stage_history, active_trackers, processed_blink_breakdown,
processed_viz_breakdown, processed_trees_in_viz_breakdown);
}
}
void LatencyUkmReporter::ReportEventLatencyUkm(
const EventMetrics::List& events_metrics,
const std::vector<CompositorFrameReporter::StageData>& stage_history,
const CompositorFrameReporter::ProcessedBlinkBreakdown&
processed_blink_breakdown,
const CompositorFrameReporter::ProcessedVizBreakdown&
processed_viz_breakdown) {
if (ukm_manager_ &&
event_latency_sampling_controller_->ShouldRecordNextEvent()) {
ukm_manager_->RecordEventLatencyUKM(events_metrics, stage_history,
processed_blink_breakdown,
processed_viz_breakdown);
}
}
void LatencyUkmReporter::InitializeUkmManager(
std::unique_ptr<ukm::UkmRecorder> recorder) {
ukm_manager_ = std::make_unique<UkmManager>(std::move(recorder));
}
void LatencyUkmReporter::SetSourceId(ukm::SourceId source_id) {
if (ukm_manager_) {
ukm_manager_->SetSourceId(source_id);
}
}
}