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

Side by Side Diff: chrome/renderer/chrome_render_process_observer.cc

Issue 1081323003: Convert renderer JS memory usage reporting to use Mojo. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@utility-process-report-js-memory
Patch Set: Fix build files. Created 5 years, 7 months 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
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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 #include "chrome/renderer/chrome_render_process_observer.h" 5 #include "chrome/renderer/chrome_render_process_observer.h"
6 6
7 #include <limits> 7 #include <limits>
8 #include <vector> 8 #include <vector>
9 9
10 #include "base/allocator/allocator_extension.h" 10 #include "base/allocator/allocator_extension.h"
11 #include "base/bind.h" 11 #include "base/bind.h"
12 #include "base/command_line.h" 12 #include "base/command_line.h"
13 #include "base/files/file_util.h" 13 #include "base/files/file_util.h"
14 #include "base/memory/weak_ptr.h" 14 #include "base/memory/weak_ptr.h"
15 #include "base/message_loop/message_loop.h" 15 #include "base/message_loop/message_loop.h"
16 #include "base/metrics/field_trial.h" 16 #include "base/metrics/field_trial.h"
17 #include "base/metrics/histogram.h" 17 #include "base/metrics/histogram.h"
18 #include "base/metrics/statistics_recorder.h" 18 #include "base/metrics/statistics_recorder.h"
19 #include "base/native_library.h" 19 #include "base/native_library.h"
20 #include "base/path_service.h" 20 #include "base/path_service.h"
21 #include "base/strings/utf_string_conversions.h" 21 #include "base/strings/utf_string_conversions.h"
22 #include "base/threading/platform_thread.h" 22 #include "base/threading/platform_thread.h"
23 #include "chrome/common/child_process_logging.h" 23 #include "chrome/common/child_process_logging.h"
24 #include "chrome/common/chrome_paths.h" 24 #include "chrome/common/chrome_paths.h"
25 #include "chrome/common/chrome_switches.h" 25 #include "chrome/common/chrome_switches.h"
26 #include "chrome/common/net/net_resource_provider.h" 26 #include "chrome/common/net/net_resource_provider.h"
27 #include "chrome/common/render_messages.h" 27 #include "chrome/common/render_messages.h"
28 #include "chrome/common/resource_usage_reporter.mojom.h"
28 #include "chrome/common/url_constants.h" 29 #include "chrome/common/url_constants.h"
29 #include "chrome/common/variations/variations_util.h" 30 #include "chrome/common/variations/variations_util.h"
30 #include "chrome/renderer/content_settings_observer.h" 31 #include "chrome/renderer/content_settings_observer.h"
31 #include "chrome/renderer/security_filter_peer.h" 32 #include "chrome/renderer/security_filter_peer.h"
32 #include "content/public/child/resource_dispatcher_delegate.h" 33 #include "content/public/child/resource_dispatcher_delegate.h"
34 #include "content/public/common/service_registry.h"
33 #include "content/public/renderer/render_thread.h" 35 #include "content/public/renderer/render_thread.h"
34 #include "content/public/renderer/render_view.h" 36 #include "content/public/renderer/render_view.h"
35 #include "content/public/renderer/render_view_visitor.h" 37 #include "content/public/renderer/render_view_visitor.h"
36 #include "crypto/nss_util.h" 38 #include "crypto/nss_util.h"
37 #include "net/base/net_errors.h" 39 #include "net/base/net_errors.h"
38 #include "net/base/net_module.h" 40 #include "net/base/net_module.h"
41 #include "third_party/mojo/src/mojo/public/cpp/bindings/strong_binding.h"
39 #include "third_party/WebKit/public/web/WebCache.h" 42 #include "third_party/WebKit/public/web/WebCache.h"
40 #include "third_party/WebKit/public/web/WebDocument.h" 43 #include "third_party/WebKit/public/web/WebDocument.h"
41 #include "third_party/WebKit/public/web/WebFrame.h" 44 #include "third_party/WebKit/public/web/WebFrame.h"
42 #include "third_party/WebKit/public/web/WebRuntimeFeatures.h" 45 #include "third_party/WebKit/public/web/WebRuntimeFeatures.h"
43 #include "third_party/WebKit/public/web/WebSecurityPolicy.h" 46 #include "third_party/WebKit/public/web/WebSecurityPolicy.h"
44 #include "third_party/WebKit/public/web/WebView.h" 47 #include "third_party/WebKit/public/web/WebView.h"
45 48
46 #if defined(ENABLE_EXTENSIONS) 49 #if defined(ENABLE_EXTENSIONS)
47 #include "chrome/renderer/extensions/extension_localization_peer.h" 50 #include "chrome/renderer/extensions/extension_localization_peer.h"
48 #endif 51 #endif
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
103 RenderThread::Get()->Send(new ChromeViewHostMsg_UpdatedCacheStats(stats)); 106 RenderThread::Get()->Send(new ChromeViewHostMsg_UpdatedCacheStats(stats));
104 } 107 }
105 108
106 base::WeakPtrFactory<RendererResourceDelegate> weak_factory_; 109 base::WeakPtrFactory<RendererResourceDelegate> weak_factory_;
107 110
108 DISALLOW_COPY_AND_ASSIGN(RendererResourceDelegate); 111 DISALLOW_COPY_AND_ASSIGN(RendererResourceDelegate);
109 }; 112 };
110 113
111 static const int kWaitForWorkersStatsTimeoutMS = 20; 114 static const int kWaitForWorkersStatsTimeoutMS = 20;
112 115
113 class HeapStatisticsCollector { 116 class ResourceUsageReporterImpl : public ResourceUsageReporter {
114 public: 117 public:
115 HeapStatisticsCollector() : round_id_(0) {} 118 explicit ResourceUsageReporterImpl(
116 119 mojo::InterfaceRequest<ResourceUsageReporter> req)
117 void InitiateCollection(); 120 : binding_(this, req.Pass()), weak_factory_(this) {}
118 static HeapStatisticsCollector* Instance(); 121 ~ResourceUsageReporterImpl() override {}
119 122
120 private: 123 private:
121 void CollectOnWorkerThread(scoped_refptr<base::TaskRunner> master, 124 static void CollectOnWorkerThread(
122 int round_id); 125 const scoped_refptr<base::TaskRunner>& master,
123 void ReceiveStats(int round_id, size_t total_size, size_t used_size); 126 base::WeakPtr<ResourceUsageReporterImpl> impl) {
124 void SendStatsToBrowser(int round_id); 127 size_t total_bytes = 0;
128 size_t used_bytes = 0;
129 v8::Isolate* isolate = v8::Isolate::GetCurrent();
130 if (isolate) {
131 v8::HeapStatistics heap_stats;
132 isolate->GetHeapStatistics(&heap_stats);
133 total_bytes = heap_stats.total_heap_size();
134 used_bytes = heap_stats.used_heap_size();
135 }
136 master->PostTask(FROM_HERE,
137 base::Bind(&ResourceUsageReporterImpl::ReceiveStats, impl,
138 total_bytes, used_bytes));
139 }
125 140
126 size_t total_bytes_; 141 void ReceiveStats(size_t total_bytes, size_t used_bytes) {
127 size_t used_bytes_; 142 usage_data_->v8_bytes_allocated += total_bytes;
143 usage_data_->v8_bytes_used += used_bytes;
144 workers_to_go_--;
145 if (!workers_to_go_)
146 SendResults();
147 }
148
149 void SendResults() {
150 if (!callback_.is_null())
151 callback_.Run(usage_data_.Pass());
152 callback_.reset();
153 weak_factory_.InvalidateWeakPtrs();
154 workers_to_go_ = 0;
155 }
156
157 void GetUsageData(
158 const mojo::Callback<void(ResourceUsageDataPtr)>& callback) override {
159 DCHECK(callback_.is_null());
160 weak_factory_.InvalidateWeakPtrs();
161 usage_data_ = ResourceUsageData::New();
162 usage_data_->reports_v8_stats = true;
163 callback_ = callback;
164
165 v8::HeapStatistics heap_stats;
166 v8::Isolate::GetCurrent()->GetHeapStatistics(&heap_stats);
167 usage_data_->v8_bytes_allocated = heap_stats.total_heap_size();
168 usage_data_->v8_bytes_used = heap_stats.used_heap_size();
169 base::Closure collect = base::Bind(
170 &ResourceUsageReporterImpl::CollectOnWorkerThread,
171 base::MessageLoopProxy::current(), weak_factory_.GetWeakPtr());
172 workers_to_go_ = RenderThread::Get()->PostTaskToAllWebWorkers(collect);
173 if (workers_to_go_) {
174 // The guard task to send out partial stats
175 // in case some workers are not responsive.
176 base::MessageLoopProxy::current()->PostDelayedTask(
177 FROM_HERE, base::Bind(&ResourceUsageReporterImpl::SendResults,
178 weak_factory_.GetWeakPtr()),
179 base::TimeDelta::FromMilliseconds(kWaitForWorkersStatsTimeoutMS));
180 } else {
181 // No worker threads so just send out the main thread data right away.
182 SendResults();
183 }
184 }
185
186 ResourceUsageDataPtr usage_data_;
187 mojo::Callback<void(ResourceUsageDataPtr)> callback_;
128 int workers_to_go_; 188 int workers_to_go_;
129 int round_id_; 189 mojo::StrongBinding<ResourceUsageReporter> binding_;
190
191 base::WeakPtrFactory<ResourceUsageReporterImpl> weak_factory_;
130 }; 192 };
131 193
132 HeapStatisticsCollector* HeapStatisticsCollector::Instance() { 194 void CreateResourceUsageReporter(
133 CR_DEFINE_STATIC_LOCAL(HeapStatisticsCollector, instance, ()); 195 mojo::InterfaceRequest<ResourceUsageReporter> request) {
134 return &instance; 196 new ResourceUsageReporterImpl(request.Pass());
135 }
136
137 void HeapStatisticsCollector::InitiateCollection() {
138 v8::HeapStatistics heap_stats;
139 v8::Isolate::GetCurrent()->GetHeapStatistics(&heap_stats);
140 total_bytes_ = heap_stats.total_heap_size();
141 used_bytes_ = heap_stats.used_heap_size();
142 base::Closure collect = base::Bind(
143 &HeapStatisticsCollector::CollectOnWorkerThread,
144 base::Unretained(this),
145 base::MessageLoopProxy::current(),
146 round_id_);
147 workers_to_go_ = RenderThread::Get()->PostTaskToAllWebWorkers(collect);
148 if (workers_to_go_) {
149 // The guard task to send out partial stats
150 // in case some workers are not responsive.
151 base::MessageLoopProxy::current()->PostDelayedTask(
152 FROM_HERE,
153 base::Bind(&HeapStatisticsCollector::SendStatsToBrowser,
154 base::Unretained(this),
155 round_id_),
156 base::TimeDelta::FromMilliseconds(kWaitForWorkersStatsTimeoutMS));
157 } else {
158 // No worker threads so just send out the main thread data right away.
159 SendStatsToBrowser(round_id_);
160 }
161 }
162
163 void HeapStatisticsCollector::CollectOnWorkerThread(
164 scoped_refptr<base::TaskRunner> master,
165 int round_id) {
166
167 size_t total_bytes = 0;
168 size_t used_bytes = 0;
169 v8::Isolate* isolate = v8::Isolate::GetCurrent();
170 if (isolate) {
171 v8::HeapStatistics heap_stats;
172 isolate->GetHeapStatistics(&heap_stats);
173 total_bytes = heap_stats.total_heap_size();
174 used_bytes = heap_stats.used_heap_size();
175 }
176 master->PostTask(
177 FROM_HERE,
178 base::Bind(&HeapStatisticsCollector::ReceiveStats,
179 base::Unretained(this),
180 round_id,
181 total_bytes,
182 used_bytes));
183 }
184
185 void HeapStatisticsCollector::ReceiveStats(int round_id,
186 size_t total_bytes,
187 size_t used_bytes) {
188 if (round_id != round_id_)
189 return;
190 total_bytes_ += total_bytes;
191 used_bytes_ += used_bytes;
192 if (!--workers_to_go_)
193 SendStatsToBrowser(round_id);
194 }
195
196 void HeapStatisticsCollector::SendStatsToBrowser(int round_id) {
197 if (round_id != round_id_)
198 return;
199 // TODO(alph): Do caching heap stats and use the cache if we haven't got
200 // reply from a worker.
201 // Currently a busy worker stats are not counted.
202 RenderThread::Get()->Send(new ChromeViewHostMsg_V8HeapStats(
203 total_bytes_, used_bytes_));
204 ++round_id_;
205 } 197 }
206 198
207 } // namespace 199 } // namespace
208 200
209 bool ChromeRenderProcessObserver::is_incognito_process_ = false; 201 bool ChromeRenderProcessObserver::is_incognito_process_ = false;
210 202
211 ChromeRenderProcessObserver::ChromeRenderProcessObserver() 203 ChromeRenderProcessObserver::ChromeRenderProcessObserver()
212 : webkit_initialized_(false) { 204 : webkit_initialized_(false) {
213 const base::CommandLine& command_line = 205 const base::CommandLine& command_line =
214 *base::CommandLine::ForCurrentProcess(); 206 *base::CommandLine::ForCurrentProcess();
215 207
216 #if defined(ENABLE_AUTOFILL_DIALOG) 208 #if defined(ENABLE_AUTOFILL_DIALOG)
217 WebRuntimeFeatures::enableRequestAutocomplete(true); 209 WebRuntimeFeatures::enableRequestAutocomplete(true);
218 #endif 210 #endif
219 211
220 if (command_line.HasSwitch(switches::kDisableJavaScriptHarmonyShipping)) { 212 if (command_line.HasSwitch(switches::kDisableJavaScriptHarmonyShipping)) {
221 std::string flag("--noharmony-shipping"); 213 std::string flag("--noharmony-shipping");
222 v8::V8::SetFlagsFromString(flag.c_str(), static_cast<int>(flag.size())); 214 v8::V8::SetFlagsFromString(flag.c_str(), static_cast<int>(flag.size()));
223 } 215 }
224 216
225 if (command_line.HasSwitch(switches::kJavaScriptHarmony)) { 217 if (command_line.HasSwitch(switches::kJavaScriptHarmony)) {
226 std::string flag("--harmony"); 218 std::string flag("--harmony");
227 v8::V8::SetFlagsFromString(flag.c_str(), static_cast<int>(flag.size())); 219 v8::V8::SetFlagsFromString(flag.c_str(), static_cast<int>(flag.size()));
228 } 220 }
229 221
230 RenderThread* thread = RenderThread::Get(); 222 RenderThread* thread = RenderThread::Get();
231 resource_delegate_.reset(new RendererResourceDelegate()); 223 resource_delegate_.reset(new RendererResourceDelegate());
232 thread->SetResourceDispatcherDelegate(resource_delegate_.get()); 224 thread->SetResourceDispatcherDelegate(resource_delegate_.get());
233 225
226 thread->GetServiceRegistry()->AddService<ResourceUsageReporter>(
227 base::Bind(CreateResourceUsageReporter));
228
234 // Configure modules that need access to resources. 229 // Configure modules that need access to resources.
235 net::NetModule::SetResourceProvider(chrome_common_net::NetResourceProvider); 230 net::NetModule::SetResourceProvider(chrome_common_net::NetResourceProvider);
236 231
237 #if defined(OS_POSIX) && !defined(OS_MACOSX) && defined(USE_NSS_CERTS) 232 #if defined(OS_POSIX) && !defined(OS_MACOSX) && defined(USE_NSS_CERTS)
238 // On platforms where we use system NSS shared libraries, 233 // On platforms where we use system NSS shared libraries,
239 // initialize NSS now because it won't be able to load the .so's 234 // initialize NSS now because it won't be able to load the .so's
240 // after we engage the sandbox. 235 // after we engage the sandbox.
241 if (!command_line.HasSwitch(switches::kSingleProcess)) 236 if (!command_line.HasSwitch(switches::kSingleProcess))
242 crypto::InitNSSSafely(); 237 crypto::InitNSSSafely();
243 #elif defined(OS_WIN) 238 #elif defined(OS_WIN)
(...skipping 10 matching lines...) Expand all
254 ChromeRenderProcessObserver::~ChromeRenderProcessObserver() { 249 ChromeRenderProcessObserver::~ChromeRenderProcessObserver() {
255 } 250 }
256 251
257 bool ChromeRenderProcessObserver::OnControlMessageReceived( 252 bool ChromeRenderProcessObserver::OnControlMessageReceived(
258 const IPC::Message& message) { 253 const IPC::Message& message) {
259 bool handled = true; 254 bool handled = true;
260 IPC_BEGIN_MESSAGE_MAP(ChromeRenderProcessObserver, message) 255 IPC_BEGIN_MESSAGE_MAP(ChromeRenderProcessObserver, message)
261 IPC_MESSAGE_HANDLER(ChromeViewMsg_SetIsIncognitoProcess, 256 IPC_MESSAGE_HANDLER(ChromeViewMsg_SetIsIncognitoProcess,
262 OnSetIsIncognitoProcess) 257 OnSetIsIncognitoProcess)
263 IPC_MESSAGE_HANDLER(ChromeViewMsg_SetFieldTrialGroup, OnSetFieldTrialGroup) 258 IPC_MESSAGE_HANDLER(ChromeViewMsg_SetFieldTrialGroup, OnSetFieldTrialGroup)
264 IPC_MESSAGE_HANDLER(ChromeViewMsg_GetV8HeapStats, OnGetV8HeapStats)
265 IPC_MESSAGE_HANDLER(ChromeViewMsg_GetCacheResourceStats, 259 IPC_MESSAGE_HANDLER(ChromeViewMsg_GetCacheResourceStats,
266 OnGetCacheResourceStats) 260 OnGetCacheResourceStats)
267 IPC_MESSAGE_HANDLER(ChromeViewMsg_SetContentSettingRules, 261 IPC_MESSAGE_HANDLER(ChromeViewMsg_SetContentSettingRules,
268 OnSetContentSettingRules) 262 OnSetContentSettingRules)
269 IPC_MESSAGE_UNHANDLED(handled = false) 263 IPC_MESSAGE_UNHANDLED(handled = false)
270 IPC_END_MESSAGE_MAP() 264 IPC_END_MESSAGE_MAP()
271 return handled; 265 return handled;
272 } 266 }
273 267
274 void ChromeRenderProcessObserver::WebKitInitialized() { 268 void ChromeRenderProcessObserver::WebKitInitialized() {
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
314 base::FieldTrial* trial = 308 base::FieldTrial* trial =
315 base::FieldTrialList::CreateFieldTrial(field_trial_name, group_name); 309 base::FieldTrialList::CreateFieldTrial(field_trial_name, group_name);
316 // TODO(mef): Remove this check after the investigation of 359406 is complete. 310 // TODO(mef): Remove this check after the investigation of 359406 is complete.
317 CHECK(trial) << field_trial_name << ":" << group_name; 311 CHECK(trial) << field_trial_name << ":" << group_name;
318 // Ensure the trial is marked as "used" by calling group() on it if it is 312 // Ensure the trial is marked as "used" by calling group() on it if it is
319 // marked as activated. 313 // marked as activated.
320 trial->group(); 314 trial->group();
321 chrome_variations::SetChildProcessLoggingVariationList(); 315 chrome_variations::SetChildProcessLoggingVariationList();
322 } 316 }
323 317
324 void ChromeRenderProcessObserver::OnGetV8HeapStats() {
325 HeapStatisticsCollector::Instance()->InitiateCollection();
326 }
327
328 const RendererContentSettingRules* 318 const RendererContentSettingRules*
329 ChromeRenderProcessObserver::content_setting_rules() const { 319 ChromeRenderProcessObserver::content_setting_rules() const {
330 return &content_setting_rules_; 320 return &content_setting_rules_;
331 } 321 }
332 322
333 void ChromeRenderProcessObserver::OnFieldTrialGroupFinalized( 323 void ChromeRenderProcessObserver::OnFieldTrialGroupFinalized(
334 const std::string& trial_name, 324 const std::string& trial_name,
335 const std::string& group_name) { 325 const std::string& group_name) {
336 content::RenderThread::Get()->Send( 326 content::RenderThread::Get()->Send(
337 new ChromeViewHostMsg_FieldTrialActivated(trial_name)); 327 new ChromeViewHostMsg_FieldTrialActivated(trial_name));
338 } 328 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698