Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(608)

Side by Side Diff: chrome/browser/metrics/tracking_synchronizer.h

Issue 8588023: Collect profiler stats from browser child processes. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 9 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #ifndef CHROME_BROWSER_METRICS_TRACKING_SYNCHRONIZER_H_ 5 #ifndef CHROME_BROWSER_METRICS_TRACKING_SYNCHRONIZER_H_
6 #define CHROME_BROWSER_METRICS_TRACKING_SYNCHRONIZER_H_ 6 #define CHROME_BROWSER_METRICS_TRACKING_SYNCHRONIZER_H_
7 #pragma once 7 #pragma once
8 8
9 #include <map> 9 #include <map>
10 #include <string> 10 #include <string>
11 #include <vector> 11 #include <vector>
12 12
13 #include "base/basictypes.h" 13 #include "base/basictypes.h"
14 #include "base/lazy_instance.h"
14 #include "base/memory/ref_counted.h" 15 #include "base/memory/ref_counted.h"
15 #include "base/memory/weak_ptr.h" 16 #include "base/memory/weak_ptr.h"
16 #include "base/time.h"
17 #include "base/values.h" 17 #include "base/values.h"
18 #include "chrome/browser/ui/webui/profiler_ui.h" 18 #include "chrome/browser/ui/webui/profiler_ui.h"
19 #include "content/common/child_process_info.h" 19 #include "content/public/browser/profiler_subscriber.h"
20 #include "content/public/browser/browser_thread.h"
21 20
22 // This class maintains state that is used to upload tracking data from the 21 // This class maintains state that is used to upload profiler data from the
23 // various processes, into the browser process. Such transactions are usually 22 // various processes, into the browser process. Such transactions are usually
24 // instigated by the browser. In general, a process will respond by gathering 23 // instigated by the browser. In general, a process will respond by gathering
25 // tracking data, and transmitting the pickled tracking data. We collect the 24 // profiler data, and transmitting the pickled profiler data. We collect the
26 // data in asynchronous mode that doesn't block the UI thread. 25 // data in asynchronous mode that doesn't block the UI thread.
27 // 26 //
28 // To assure that all the processes have responded, a counter is maintained 27 // To assure that all the processes have responded, a counter is maintained
29 // to indicate the number of pending (not yet responsive) processes. We tag 28 // to indicate the number of pending (not yet responsive) processes. We tag
30 // each group of requests with a sequence number. For each group of requests, we 29 // each group of requests with a sequence number. For each group of requests, we
31 // create RequestContext object which stores the sequence number, pending 30 // create RequestContext object which stores the sequence number, pending
32 // processes and the callback_object that needs to be notified when we receive 31 // processes and the callback_object that needs to be notified when we receive
33 // an update from processes. When an update arrives we find the RequestContext 32 // an update from processes. When an update arrives we find the RequestContext
34 // associated with sequence number and send the unpickled tracking data to the 33 // associated with sequence number and send the unpickled profiler data to the
35 // |callback_object_|. 34 // |callback_object_|.
36 35
37 namespace chrome_browser_metrics { 36 namespace chrome_browser_metrics {
38 37
39 class TrackingSynchronizer : public 38 class RequestContext;
40 base::RefCountedThreadSafe<TrackingSynchronizer> { 39
40 class TrackingSynchronizer
41 : public ProfilerSubscriber,
42 public base::RefCountedThreadSafe<TrackingSynchronizer> {
41 public: 43 public:
42 // The "RequestContext" structure describes an individual request received
43 // from the UI.
44 struct RequestContext {
45 RequestContext(const base::WeakPtr<ProfilerUI>& callback_object,
46 int sequence_number,
47 int processes_pending,
48 base::TimeTicks callback_start_time)
49 : callback_object_(callback_object),
50 sequence_number_(sequence_number),
51 processes_pending_(processes_pending),
52 request_start_time_(callback_start_time) {
53 }
54
55 ~RequestContext() {}
56
57 // Requests are made to asynchronously send data to the |callback_object_|.
58 base::WeakPtr<ProfilerUI> callback_object_;
59
60 // The sequence number used by the most recent update request to contact all
61 // processes.
62 int sequence_number_;
63
64 // The number of processes that have not yet responded to requests.
65 int processes_pending_;
66
67 // The time when we were told to start the fetching of data from processes.
68 base::TimeTicks request_start_time_;
69 };
70
71 // A map from sequence_number_ to the actual RequestContexts.
72 typedef std::map<int, RequestContext*> RequestContextMap;
73
74 // Construction also sets up the global singleton instance. This instance is 44 // Construction also sets up the global singleton instance. This instance is
75 // used to communicate between the IO and UI thread, and is destroyed only as 45 // used to communicate between the IO and UI thread, and is destroyed only as
76 // the main thread (browser_main) terminates, which means the IO thread has 46 // the main thread (browser_main) terminates, which means the IO thread has
77 // already completed, and will not need this instance any further. 47 // already completed, and will not need this instance any further.
78 TrackingSynchronizer(); 48 TrackingSynchronizer();
79 49
80 // Return pointer to the singleton instance, which is allocated and
81 // deallocated on the main UI thread (during system startup and teardown).
82 static TrackingSynchronizer* CurrentSynchronizer();
83
84 // Contact all processes, and get them to upload to the browser any/all 50 // Contact all processes, and get them to upload to the browser any/all
85 // changes to tracking data. It calls |callback_object|'s SetData method with 51 // changes to profiler data. It calls |callback_object|'s SetData method with
86 // the data received from each sub-process. 52 // the data received from each sub-process.
87 // This method is accessible on UI thread. 53 // This method is accessible on UI thread.
88 static void FetchTrackingDataAsynchronously( 54 static void FetchProfilerDataAsynchronously(
89 const base::WeakPtr<ProfilerUI>& callback_object); 55 const base::WeakPtr<ProfilerUI>& callback_object);
90 56
91 // Contact all processes and set tracking status to |enable|. 57 // ------------------------------------------------------
92 // This method is accessible on UI thread. 58 // ProfilerSubscriber methods for browser child processes
93 static void SetTrackingStatus(bool enable); 59 // ------------------------------------------------------
94 60
95 // Respond to this message from the renderer by setting the tracking status 61 // Update the number of pending processes for the given |sequence_number|.
96 // (SetTrackingStatusInProcess) in that renderer process. 62 // This is called on UI thread.
97 // |process_id| is used to find the renderer process. 63 virtual void OnPendingProcesses(int sequence_number,
64 int pending_processes) OVERRIDE;
65
66 // Post a task on UI thread to call OnProfilerDataCollectedOnUI which sends
67 // profiler_data back to callback_object_.
98 // This method is accessible on IO thread. 68 // This method is accessible on IO thread.
99 static void IsTrackingEnabled(int process_id); 69 virtual void OnProfilerDataCollected(
100
101 // Get the current tracking status from the browser process and set it in the
102 // renderer process. |process_id| is used to find the renderer process.
103 // This method is accessible on UI thread.
104 static void SetTrackingStatusInProcess(int process_id);
105
106 // Deserialize the tracking data and record that we have received tracking
107 // data from a process. This method posts a task to call
108 // DeserializeTrackingListOnUI on UI thread to send the |tracking_data| to
109 // callback_object_. This method is accessible on IO thread.
110 static void DeserializeTrackingList(
111 int sequence_number, 70 int sequence_number,
112 const std::string& tracking_data, 71 const base::DictionaryValue& profiler_data) OVERRIDE;
113 ChildProcessInfo::ProcessType process_type);
114
115 // Deserialize the tracking data and record that we have received tracking
116 // data from a process. This method is accessible on UI thread.
117 static void DeserializeTrackingListOnUI(
118 int sequence_number,
119 const std::string& tracking_data,
120 ChildProcessInfo::ProcessType process_type);
121 72
122 private: 73 private:
123 friend class base::RefCountedThreadSafe<TrackingSynchronizer>; 74 friend class base::RefCountedThreadSafe<TrackingSynchronizer>;
75 friend class RequestContext;
124 76
125 virtual ~TrackingSynchronizer(); 77 virtual ~TrackingSynchronizer();
126 78
79 // Send profiler_data back to callback_object_. It records that we are waiting
80 // for one less profiler data from renderer or browser child process for the
81 // given sequence number. This method is accessible on UI thread.
82 void OnProfilerDataCollectedOnUI(int sequence_number,
83 base::DictionaryValue* profiler_data);
84
127 // Establish a new sequence_number_, and use it to notify all the processes of 85 // Establish a new sequence_number_, and use it to notify all the processes of
128 // the need to supply, to the browser, their tracking data. It also registers 86 // the need to supply, to the browser, their tracking data. It also registers
129 // |callback_object| in |outstanding_requests_| map. Return the 87 // |callback_object| in |outstanding_requests_| map. Return the
130 // sequence_number_ that was used. This method is accessible on UI thread. 88 // sequence_number_ that was used. This method is accessible on UI thread.
131 int RegisterAndNotifyAllProcesses( 89 int RegisterAndNotifyAllProcesses(
132 const base::WeakPtr<ProfilerUI>& callback_object); 90 const base::WeakPtr<ProfilerUI>& callback_object);
133 91
134 // It finds the |callback_object_| in |outstanding_requests_| map for the 92 // It finds the RequestContext for the given |sequence_number| and notifies
135 // given |sequence_number| and notifies the |callback_object_| about the 93 // the RequestContext's |callback_object_| about the |value|. This is called
136 // |value|. This is called whenever we receive tracked data from processes. It 94 // whenever we receive profiler data from processes. It also records that we
137 // also records that we are waiting for one less tracking data from a process 95 // are waiting for one less profiler data from a process for the given
138 // for the given sequence number. If we have received a response from all 96 // sequence number. If we have received a response from all renderers and
139 // renderers, then it deletes the entry for sequence_number from 97 // browser processes, then it calls RequestContext's DeleteIfAllDone to delete
140 // |outstanding_requests_| map. This method is accessible on UI thread. 98 // the entry for sequence_number. This method is accessible on UI thread.
141 void DecrementPendingProcessesAndSendData(int sequence_number, 99 void DecrementPendingProcessesAndSendData(int sequence_number,
142 base::DictionaryValue* value); 100 base::DictionaryValue* value);
143 101
144 // Records that we are waiting for one less tracking data from a process for
145 // the given sequence number.
146 // This method is accessible on UI thread.
147 void DecrementPendingProcesses(int sequence_number);
148
149 // When all changes have been acquired, or when the wait time expires
150 // (whichever is sooner), this method is called. This method deletes the entry
151 // for the given sequence_number from |outstanding_requests_| map.
152 // This method is accessible on UI thread.
153 void ForceTrackingSynchronizationDoneCallback(int sequence_number);
154
155 // Get a new sequence number to be sent to processes from browser process. 102 // Get a new sequence number to be sent to processes from browser process.
156 // This method is accessible on UI thread. 103 // This method is accessible on UI thread.
157 int GetNextAvailableSequenceNumber(); 104 int GetNextAvailableSequenceNumber();
158 105
159 // Map of all outstanding RequestContexts, from sequence_number_ to 106 // Return pointer to the singleton instance, which is allocated and
160 // RequestContext. 107 // deallocated on the main UI thread (during system startup and teardown).
161 RequestContextMap outstanding_requests_; 108 // This method is accessible on UI thread.
109 static TrackingSynchronizer* CurrentSynchronizer();
162 110
163 // We don't track the actual processes that are contacted for an update, only 111 // We don't track the actual processes that are contacted for an update, only
164 // the count of the number of processes, and we can sometimes time-out and 112 // the count of the number of processes, and we can sometimes time-out and
165 // give up on a "slow to respond" process. We use a sequence_number to be 113 // give up on a "slow to respond" process. We use a sequence_number to be
166 // sure a response from a process is associated with the current round of 114 // sure a response from a process is associated with the current round of
167 // requests. All sequence numbers used are non-negative. 115 // requests. All sequence numbers used are non-negative.
168 // last_used_sequence_number_ is the most recently used number (used to avoid 116 // last_used_sequence_number_ is the most recently used number (used to avoid
169 // reuse for a long time). 117 // reuse for a long time).
170 int last_used_sequence_number_; 118 int last_used_sequence_number_;
171 119
172 // This singleton instance should be started during the single threaded 120 // This singleton instance should be started during the single threaded
173 // portion of main(). It initializes globals to provide support for all future 121 // portion of main(). It initializes globals to provide support for all future
174 // calls. This object is created on the UI thread, and it is destroyed after 122 // calls. This object is created on the UI thread, and it is destroyed after
175 // all the other threads have gone away. As a result, it is ok to call it 123 // all the other threads have gone away. As a result, it is ok to call it
176 // from the UI thread, or for about:tracking. 124 // from the UI thread, or for about:profiler.
177 static TrackingSynchronizer* tracking_synchronizer_; 125 static TrackingSynchronizer* tracking_synchronizer_;
178 126
179 DISALLOW_COPY_AND_ASSIGN(TrackingSynchronizer); 127 DISALLOW_COPY_AND_ASSIGN(TrackingSynchronizer);
180 }; 128 };
181 129
130 // The "RequestContext" structure describes an individual request received
131 // from the UI. All methods are accessible on UI thread.
132 class RequestContext {
jam 2011/11/28 15:17:34 is this class used by other files, or only trackin
ramant (doing other things) 2011/11/29 01:32:20 Done.
133 public:
134 // A map from sequence_number_ to the actual RequestContexts.
135 typedef std::map<int, RequestContext*> RequestContextMap;
136
137 ~RequestContext();
138
139 private:
140 friend class TrackingSynchronizer;
141
142 RequestContext(const base::WeakPtr<ProfilerUI>& callback_object,
143 int sequence_number);
144
145 // Methods for book keeping of process_group_count_.
146 void AddProcessGroupCount(int process_group_count);
147 void DecrementProcessGroupCount();
148
149 // Methods for book keeping of processes_pending_.
150 void IncrementProcessesPending();
151 void AddProcessesPending(int processes_pending);
152 void DecrementProcessesPending();
153
154 // Records that we are waiting for one less tracking data from a process for
155 // the given sequence number. If |process_group_count_| and
156 // |processes_pending_| are zero, then delete the current object by calling
157 // Unregister.
158 void DeleteIfAllDone();
159
160 // Register |callback_object| in |outstanding_requests_| map for the given
161 // |sequence_number|.
162 static RequestContext* Register(
163 int sequence_number,
164 const base::WeakPtr<ProfilerUI>& callback_object);
165
166 // Find the |RequestContext| in |outstanding_requests_| map for the given
167 // |sequence_number|.
168 static RequestContext* GetRequestContext(int sequence_number);
169
170 // Delete the entry for the given sequence_number| from
171 // |outstanding_requests_| map. This method is called when all changes have
172 // been acquired, or when the wait time expires (whichever is sooner).
173 static void Unregister(int sequence_number);
174
175 // Delete all the entries in |outstanding_requests_| map.
176 static void OnShutdown();
177
178 // Requests are made to asynchronously send data to the |callback_object_|.
179 base::WeakPtr<ProfilerUI> callback_object_;
180
181 // The sequence number used by the most recent update request to contact all
182 // processes.
183 int sequence_number_;
184
185 // The number of times we need to hear from |content| about number of
186 // pending processes. |content| code calls OnPendingProcesses once for
187 // RenderProcessHosts and another time for BrowserChildProcessHosts after
188 // sending GetChildProfilerData message to all respective child processes.
189 // RegisterAndNotifyAllProcesses initializes it by the value returned by the
190 // content::GetProfilerData and OnPendingProcesses decrements it when it gets
191 // processes pending count.
192 int process_group_count_;
193
194 // The number of pending processes (browser, all renderer processes and
195 // browser child processes) that have not yet responded to requests.
196 int processes_pending_;
197
198 // Map of all outstanding RequestContexts, from sequence_number_ to
199 // RequestContext.
200 static base::LazyInstance<RequestContextMap> outstanding_requests_;
201 };
202
182 } // namespace chrome_browser_metrics 203 } // namespace chrome_browser_metrics
183 204
184 #endif // CHROME_BROWSER_METRICS_TRACKING_SYNCHRONIZER_H_ 205 #endif // CHROME_BROWSER_METRICS_TRACKING_SYNCHRONIZER_H_
OLDNEW
« no previous file with comments | « no previous file | chrome/browser/metrics/tracking_synchronizer.cc » ('j') | chrome/browser/metrics/tracking_synchronizer.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698