// 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. #ifndef BASE_TRACE_EVENT_CPUFREQ_MONITOR_ANDROID_H_ #define BASE_TRACE_EVENT_CPUFREQ_MONITOR_ANDROID_H_ #include "base/atomicops.h" #include "base/base_export.h" #include "base/files/scoped_file.h" #include "base/memory/scoped_refptr.h" #include "base/trace_event/trace_log.h" namespace base { class SingleThreadTaskRunner; namespace trace_event { // A delegate to isolate CPU frequency monitor functionality mainly for testing. class BASE_EXPORT CPUFreqMonitorDelegate { public: CPUFreqMonitorDelegate(); virtual ~CPUFreqMonitorDelegate() = default; // Returns a vector of the minimal set of CPU IDs that we need to monitor to // get CPU frequency information. For CPUs that operate cores in a cluster, // i.e. modern Qualcomm 8 cores, this is CPU0 and CPU4. virtual void GetCPUIds(std::vector* ids) const; // Reads the kernel_max_cpu file to determine the max CPU ID, i.e. 7 on an // 8-core CPU. virtual unsigned int GetKernelMaxCPUs() const; // Reads the frequency from the CPUs being monitored and records them. virtual void RecordFrequency(unsigned int cpu_id, unsigned int freq); // Returns whether or not the tracing category our CPU Frequency counters are // in is enabled to determine if we should record. virtual bool IsTraceCategoryEnabled() const; // Gets the path to CPU frequency related files for a particular CPU ID. virtual std::string GetScalingCurFreqPathString(unsigned int cpu_id) const; virtual std::string GetRelatedCPUsPathString(unsigned int cpu_id) const; // Allows us to delay creating a task runner, necessary because many tests // don't like us creating one outside of a ScopedTaskEnvironment. virtual scoped_refptr CreateTaskRunner(); private: DISALLOW_COPY_AND_ASSIGN(CPUFreqMonitorDelegate); }; // A class for monitoring the CPU frequency on unique cores/clusters. class BASE_EXPORT CPUFreqMonitor : public TraceLog::EnabledStateObserver { public: // Overhead of reading one cluster on a Nexus 6P is ~0.1ms per CPU. 50ms seems // frequent enough to get a general idea of CPU frequency trends. static const size_t kDefaultCPUFreqSampleIntervalMs = 50; CPUFreqMonitor(); ~CPUFreqMonitor() override; static CPUFreqMonitor* GetInstance(); void Start(); void Stop(); // TraceLog::EnabledStateObserver. void OnTraceLogEnabled() override; void OnTraceLogDisabled() override; bool IsEnabledForTesting(); private: friend class CPUFreqMonitorTest; CPUFreqMonitor(std::unique_ptr delegate); void Sample(std::vector> fds); // Uses the delegate's CreateTaskRunner function to lazily create a task // runner so we don't illegally create a task runner on Chrome startup for // various tests. const scoped_refptr& GetOrCreateTaskRunner(); base::subtle::Atomic32 is_enabled_ = 0; scoped_refptr task_runner_; std::unique_ptr delegate_; base::WeakPtrFactory weak_ptr_factory_; DISALLOW_COPY_AND_ASSIGN(CPUFreqMonitor); }; } // namespace trace_event } // namespace base #endif // BASE_TRACE_EVENT_CPUFREQ_MONITOR_ANDROID_H_