1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef CHROME_BROWSER_TASK_MANAGER_SAMPLING_SHARED_SAMPLER_H_
6 #define CHROME_BROWSER_TASK_MANAGER_SAMPLING_SHARED_SAMPLER_H_
7 
8 #include <map>
9 #include <memory>
10 #include <utility>
11 #include <vector>
12 
13 #include "base/callback.h"
14 #include "base/files/file_path.h"
15 #include "base/macros.h"
16 #include "base/memory/ref_counted.h"
17 #include "base/optional.h"
18 #include "base/process/process_handle.h"
19 #include "base/sequence_checker.h"
20 #include "base/sequenced_task_runner.h"
21 #include "base/time/time.h"
22 #include "build/build_config.h"
23 
24 namespace task_manager {
25 
26 struct ProcessDataSnapshot;
27 
28 // Defines sampler that will calculate resources for all processes all at once,
29 // on the worker thread. Created by TaskManagerImpl on the UI thread, but used
30 // mainly on a blocking pool thread.
31 //
32 // This exists because on Windows it is much faster to collect a group of
33 // process metrics for all processes all at once using NtQuerySystemInformation
34 // than to query the same data for for each process individually and because
35 // some types like Idle Wakeups can only be collected this way.
36 class SharedSampler : public base::RefCountedThreadSafe<SharedSampler> {
37  public:
38   explicit SharedSampler(
39       const scoped_refptr<base::SequencedTaskRunner>& blocking_pool_runner);
40 
41   struct SamplingResult {
42     base::TimeDelta cpu_time;
43     int64_t hard_faults_per_second;
44     int idle_wakeups_per_second;
45     base::Time start_time;
46   };
47   using OnSamplingCompleteCallback =
48       base::RepeatingCallback<void(base::Optional<SamplingResult>)>;
49 
50   // Returns a combination of refresh flags supported by the shared sampler.
51   int64_t GetSupportedFlags() const;
52 
53   // Registers task group specific callbacks.
54   void RegisterCallback(base::ProcessId process_id,
55                         OnSamplingCompleteCallback on_sampling_complete);
56 
57   // Unregisters task group specific callbacks.
58   void UnregisterCallback(base::ProcessId process_id);
59 
60   // Triggers a refresh of the expensive process' stats, on the worker thread.
61   void Refresh(base::ProcessId process_id, int64_t refresh_flags);
62 
63 #if defined(OS_WIN)
64   // Specifies a function to use in place of NtQuerySystemInformation.
65   typedef int (*QuerySystemInformationForTest)(unsigned char* buffer,
66                                                int buffer_size);
67   static void SetQuerySystemInformationForTest(
68       QuerySystemInformationForTest query_system_information);
69 #endif  // defined(OS_WIN)
70 
71  private:
72   friend class base::RefCountedThreadSafe<SharedSampler>;
73   ~SharedSampler();
74 
75   typedef std::map<base::ProcessId, OnSamplingCompleteCallback> CallbacksMap;
76 
77 #if defined(OS_WIN)
78   // Contains all results of refresh for a single process.
79   struct ProcessIdAndSamplingResult {
80     base::ProcessId process_id;
81     SamplingResult data;
82   };
83   typedef std::vector<ProcessIdAndSamplingResult> AllSamplingResults;
84 
85   // Posted on the worker thread to do the actual refresh.
86   AllSamplingResults RefreshOnWorkerThread();
87 
88   // Called on UI thread when the refresh is done.
89   void OnRefreshDone(AllSamplingResults sampling_results);
90 
91   // Clear cached data.
92   void ClearState();
93 
94   // Used to filter process information.
95   static std::vector<base::FilePath> GetSupportedImageNames();
96   bool IsSupportedImageName(base::FilePath::StringPieceType image_name) const;
97 
98   // Captures a snapshot of data for all chrome processes.
99   // Runs on the worker thread.
100   std::unique_ptr<ProcessDataSnapshot> CaptureSnapshot();
101 
102   // Produce refresh results by diffing two snapshots.
103   static AllSamplingResults MakeResultsFromTwoSnapshots(
104       const ProcessDataSnapshot& prev_snapshot,
105       const ProcessDataSnapshot& snapshot);
106 
107   // Produce refresh results from one snapshot.
108   // This is used only the first time when only one snapshot is available.
109   static AllSamplingResults MakeResultsFromSnapshot(
110       const ProcessDataSnapshot& snapshot);
111 
112   // Accumulates callbacks passed from TaskGroup objects passed via
113   // RegisterCallbacks calls.
114   CallbacksMap callbacks_map_;
115 
116   // Refresh flags passed via Refresh.
117   int64_t refresh_flags_;
118 
119   // Snapshot of previously captured resources used to calculate the delta.
120   std::unique_ptr<ProcessDataSnapshot> previous_snapshot_;
121 
122   // Size of the buffer previously used to query system information.
123   size_t previous_buffer_size_;
124 
125   // Image names that CaptureSnapshot uses to filter processes.
126   const std::vector<base::FilePath> supported_image_names_;
127 
128   // The specific blocking pool SequencedTaskRunner that will be used to post
129   // the refresh tasks onto serially.
130   scoped_refptr<base::SequencedTaskRunner> blocking_pool_runner_;
131 
132   // To assert we're running on the correct thread.
133   base::SequenceChecker worker_pool_sequenced_checker_;
134 #endif  // defined(OS_WIN)
135 
136   DISALLOW_COPY_AND_ASSIGN(SharedSampler);
137 };
138 
139 }  // namespace task_manager
140 
141 #endif  // CHROME_BROWSER_TASK_MANAGER_SAMPLING_SHARED_SAMPLER_H_
142