Index: chrome/browser/metrics/subprocess_metrics_provider.cc |
diff --git a/chrome/browser/metrics/subprocess_metrics_provider.cc b/chrome/browser/metrics/subprocess_metrics_provider.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..b6b7eb5a3e2abf60312692b459b6077518e03132 |
--- /dev/null |
+++ b/chrome/browser/metrics/subprocess_metrics_provider.cc |
@@ -0,0 +1,126 @@ |
+// Copyright 2016 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. |
+ |
+#include "chrome/browser/metrics/subprocess_metrics_provider.h" |
+ |
+#include "base/logging.h" |
+#include "base/metrics/histogram_base.h" |
+#include "base/metrics/histogram_macros.h" |
+#include "base/metrics/histogram_persistence.h" |
+#include "base/metrics/persistent_memory_allocator.h" |
+#include "components/metrics/metrics_service.h" |
+#include "content/public/browser/notification_service.h" |
+#include "content/public/browser/notification_types.h" |
+#include "content/public/browser/render_process_host.h" |
+ |
+namespace metrics { |
Alexei Svitkine (slow)
2016/03/24 17:29:53
The metrics namespace is for code in components/me
bcwhite
2016/03/29 11:53:27
Done.
|
+ |
+SubprocessMetricsProvider::SubprocessMetricsProvider() |
+ : scoped_observer_(this) { |
+ registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_CREATED, |
Alexei Svitkine (slow)
2016/03/24 17:29:53
I think notifications are deprecated. Is there a w
bcwhite
2016/03/29 11:53:27
Some notifications are deprecated but I couldn't f
|
+ content::NotificationService::AllBrowserContextsAndSources()); |
+} |
+ |
+SubprocessMetricsProvider::~SubprocessMetricsProvider() { |
+} |
+ |
+void SubprocessMetricsProvider::RegisterSubprocessAllocator( |
+ int id, |
+ scoped_ptr<base::SharedPersistentMemoryAllocator> allocator) { |
+ DCHECK(thread_checker_.CalledOnValidThread()); |
+ DCHECK(!allocators_by_id_.Lookup(id)); |
+ |
+ // Map is "MapOwnPointer" so transfer ownership to it. |
+ allocators_by_id_.AddWithID(allocator.release(), id); |
+} |
+ |
+void SubprocessMetricsProvider::DeregisterSubprocessAllocator(int id) { |
+ DCHECK(thread_checker_.CalledOnValidThread()); |
+ if (!allocators_by_id_.Lookup(id)) |
+ return; |
+ |
+ // Transfer allocator from "active" list to "release" list. |
+ allocators_to_release_.push_back( |
+ make_scoped_ptr(allocators_by_id_.Replace(id, nullptr))); |
+ allocators_by_id_.Remove(id); |
+} |
+ |
+void SubprocessMetricsProvider::RecordHistogramSnapshotsFromAllocator( |
+ base::HistogramSnapshotManager* snapshot_manager, |
+ int id, |
+ base::SharedPersistentMemoryAllocator* allocator) { |
+ DCHECK(allocator); |
+ |
+ int histogram_count = 0; |
+ base::PersistentMemoryAllocator::Iterator hist_iter; |
+ allocator->CreateIterator(&hist_iter); |
+ while (true) { |
+ scoped_ptr<base::HistogramBase> histogram( |
+ base::GetNextPersistentHistogram(allocator, &hist_iter)); |
+ if (!histogram) |
+ break; |
+ snapshot_manager->PrepareDeltaTakingOwnership(std::move(histogram)); |
+ ++histogram_count; |
+ } |
+ |
+ DVLOG(1) << "Reported " << histogram_count << " histograms from subprocess #" |
+ << id; |
+} |
+ |
+void SubprocessMetricsProvider::RecordHistogramSnapshots( |
+ base::HistogramSnapshotManager* snapshot_manager) { |
+ DCHECK(thread_checker_.CalledOnValidThread()); |
+ |
+ for (AllocatorByIdMap::iterator iter(&allocators_by_id_); !iter.IsAtEnd(); |
+ iter.Advance()) { |
+ RecordHistogramSnapshotsFromAllocator( |
+ snapshot_manager, iter.GetCurrentKey(), iter.GetCurrentValue()); |
+ } |
+ |
+ for (auto& allocator : allocators_to_release_) |
+ RecordHistogramSnapshotsFromAllocator(snapshot_manager, 0, allocator.get()); |
+ |
+ UMA_HISTOGRAM_COUNTS_100( |
+ "UMA.SubprocessMetricsProvider.SubproccessCount", |
+ allocators_by_id_.size() + allocators_to_release_.size()); |
+ |
+ // The snapshot-manager has taken ownership of the histograms but needs |
+ // access to only the histogram objects, not "sample" data it uses. Thus, |
+ // it is safe to release shared-memory segments without for the snapshot- |
+ // manager to "finish". |
+ allocators_to_release_.clear(); |
+} |
+ |
+void SubprocessMetricsProvider::Observe( |
+ int type, |
+ const content::NotificationSource& source, |
+ const content::NotificationDetails& details) { |
+ DCHECK(thread_checker_.CalledOnValidThread()); |
+ DCHECK_EQ(content::NOTIFICATION_RENDERER_PROCESS_CREATED, type); |
+ content::RenderProcessHost* host = |
+ content::Source<content::RenderProcessHost>(source).ptr(); |
+ |
+ // Sometimes, the same host will cause multiple notifications in tests so |
+ // could possibly do the same in a release build. |
+ if (!scoped_observer_.IsObserving(host)) |
+ scoped_observer_.Add(host); |
+} |
+ |
+void SubprocessMetricsProvider::RenderProcessReady( |
+ content::RenderProcessHost* host) { |
+ DCHECK(thread_checker_.CalledOnValidThread()); |
+ scoped_ptr<base::SharedPersistentMemoryAllocator> allocator = |
+ host->GetMetricsAllocator(); |
+ if (allocator) |
+ RegisterSubprocessAllocator(host->GetID(), std::move(allocator)); |
+} |
+ |
+void SubprocessMetricsProvider::RenderProcessHostDestroyed( |
+ content::RenderProcessHost* host) { |
+ DCHECK(thread_checker_.CalledOnValidThread()); |
+ DeregisterSubprocessAllocator(host->GetID()); |
+ scoped_observer_.Remove(host); |
+} |
+ |
+} // namespace metrics |