blob: d78786885c244e27b6dee9373021531d2482171d [file] [log] [blame]
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef COMPONENTS_PERFORMANCE_MANAGER_RESOURCE_ATTRIBUTION_QUERY_SCHEDULER_H_
#define COMPONENTS_PERFORMANCE_MANAGER_RESOURCE_ATTRIBUTION_QUERY_SCHEDULER_H_
#include <memory>
#include <optional>
#include <utility>
#include <vector>
#include "base/functional/callback_forward.h"
#include "base/functional/callback_helpers.h"
#include "base/memory/weak_ptr.h"
#include "base/sequence_checker.h"
#include "components/performance_manager/public/graph/graph_registered.h"
#include "components/performance_manager/public/resource_attribution/query_results.h"
#include "components/performance_manager/public/resource_attribution/resource_contexts.h"
#include "components/performance_manager/public/resource_attribution/resource_types.h"
#include "components/performance_manager/resource_attribution/cpu_measurement_monitor.h"
#include "components/performance_manager/resource_attribution/memory_measurement_provider.h"
#include "components/performance_manager/resource_attribution/performance_manager_aliases.h"
#include "components/performance_manager/resource_attribution/query_params.h"
#include "third_party/abseil-cpp/absl/container/flat_hash_map.h"
namespace base {
class ScopedUmaHistogramTimer;
}
namespace performance_manager {
class Graph;
}
namespace resource_attribution {
class ContextCollection;
}
namespace resource_attribution::internal {
// QueryScheduler keeps track of all queries for a particular resource type and
// owns the machinery that performs measurements.
class QueryScheduler
: public performance_manager::GraphOwnedAndRegistered<QueryScheduler> {
public:
QueryScheduler();
~QueryScheduler() override;
QueryScheduler(const QueryScheduler&) = delete;
QueryScheduler& operator=(const QueryScheduler&) = delete;
// Returns the singleton QueryScheduler, or nullptr if none exists. This is
// equivalent to QueryScheduler::GetFromGraph(nullptr), but also works in
// unit tests using GraphTestHarness.
static QueryScheduler* Get();
base::WeakPtr<QueryScheduler> GetWeakPtr();
// Adds a scoped query for `query_params`. Increases the query count for all
// resource types and contexts referenced in `query_params`.
void AddScopedQuery(QueryParams* query_params);
// Decreases the query count for all resource types and contexts referenced in
// `query_params` and deletes `query_params`.
void RemoveScopedQuery(std::unique_ptr<QueryParams> query_params);
// Notifies the scheduler that a scoped query will begin repeatedly requesting
// results. The query now needs a QueryId to track what results it has
// received. If `passive_observer_callback` is not null, it will be called for
// results from all queries that match `query_params`.
void StartRepeatingQuery(QueryParams* query_params,
base::RepeatingCallback<void(const QueryResultMap&)>
passive_observer_callback =
base::NullCallback());
// Requests the latest results for the given `query_params`, and passes them
// to `callback`.
void RequestResults(const QueryParams& query_params,
base::OnceCallback<void(const QueryResultMap&)> callback);
// GraphOwned:
void OnPassedToGraph(Graph* graph) final;
void OnTakenFromGraph(Graph* graph) final;
// Gives tests direct access to `cpu_monitor_`.
CPUMeasurementMonitor& GetCPUMonitorForTesting();
// Gives tests direct access to `memory_provider_`.
MemoryMeasurementProvider& GetMemoryProviderForTesting();
// Gives tests access to the query count for `resource_type`.
uint32_t GetQueryCountForTesting(ResourceType resource_type) const;
// Logs metrics on Resource Attribution's memory usage to UMA.
void RecordMemoryMetrics();
private:
// Increases the CPU query count. `cpu_monitor_` will start monitoring CPU
// usage when the count > 0.
void AddCPUQuery();
// Decreases the CPU query count. `cpu_monitor_` will stop monitoring CPU
// usage when the count == 0.
void RemoveCPUQuery();
// Increases the memory query count.
void AddMemoryQuery();
// Decreases the memory query count.
void RemoveMemoryQuery();
// Invoked from RequestResults when all results for `query_id` are received.
// `all_results` will contain a separate result map for each ResourceType that
// was requested. Combines them int a single result map associating all
// results for each context in `contexts`, and passes it to `callback`.
// `request_timer` logs the time from the beginning of RequestResults to the
// end of this function.
void OnResultsReceived(
const std::optional<QueryId>& query_id,
const ContextCollection& contexts,
std::unique_ptr<base::ScopedUmaHistogramTimer> request_timer,
base::OnceCallback<void(const QueryResultMap&)> callback,
std::vector<QueryResultMap> all_results);
SEQUENCE_CHECKER(sequence_checker_);
// Copies of the queries that are observing all results.
absl::flat_hash_map<
QueryId,
std::pair<std::unique_ptr<QueryParams>,
base::RepeatingCallback<void(const QueryResultMap&)>>>
passive_observer_queries_ GUARDED_BY_CONTEXT(sequence_checker_);
// CPU measurement machinery.
CPUMeasurementMonitor cpu_monitor_ GUARDED_BY_CONTEXT(sequence_checker_);
uint32_t cpu_query_count_ GUARDED_BY_CONTEXT(sequence_checker_) = 0;
// Memory measurement machinery.
std::optional<MemoryMeasurementProvider> memory_provider_
GUARDED_BY_CONTEXT(sequence_checker_);
uint32_t memory_query_count_ GUARDED_BY_CONTEXT(sequence_checker_) = 0;
base::WeakPtrFactory<QueryScheduler> weak_factory_{this};
};
} // namespace resource_attribution::internal
#endif // COMPONENTS_PERFORMANCE_MANAGER_RESOURCE_ATTRIBUTION_QUERY_SCHEDULER_H_