| OLD | NEW |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 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 | 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/browser/metrics/subprocess_metrics_provider.h" | 5 #include "chrome/browser/metrics/subprocess_metrics_provider.h" |
| 6 | 6 |
| 7 #include "base/logging.h" | 7 #include "base/logging.h" |
| 8 #include "base/memory/ptr_util.h" | 8 #include "base/memory/ptr_util.h" |
| 9 #include "base/metrics/histogram_base.h" | 9 #include "base/metrics/histogram_base.h" |
| 10 #include "base/metrics/histogram_macros.h" | 10 #include "base/metrics/histogram_macros.h" |
| (...skipping 21 matching lines...) Expand all Loading... |
| 32 // Map is "MapOwnPointer" so transfer ownership to it. | 32 // Map is "MapOwnPointer" so transfer ownership to it. |
| 33 allocators_by_id_.AddWithID(allocator.release(), id); | 33 allocators_by_id_.AddWithID(allocator.release(), id); |
| 34 } | 34 } |
| 35 | 35 |
| 36 void SubprocessMetricsProvider::DeregisterSubprocessAllocator(int id) { | 36 void SubprocessMetricsProvider::DeregisterSubprocessAllocator(int id) { |
| 37 DCHECK(thread_checker_.CalledOnValidThread()); | 37 DCHECK(thread_checker_.CalledOnValidThread()); |
| 38 | 38 |
| 39 if (!allocators_by_id_.Lookup(id)) | 39 if (!allocators_by_id_.Lookup(id)) |
| 40 return; | 40 return; |
| 41 | 41 |
| 42 // Extract the matching allocator from the list of active ones. | 42 // Extract the matching allocator from the list of active ones. It will |
| 43 // be automatically released when this method exits. |
| 43 std::unique_ptr<base::PersistentHistogramAllocator> allocator( | 44 std::unique_ptr<base::PersistentHistogramAllocator> allocator( |
| 44 allocators_by_id_.Replace(id, nullptr)); | 45 allocators_by_id_.Replace(id, nullptr)); |
| 45 allocators_by_id_.Remove(id); | 46 allocators_by_id_.Remove(id); |
| 46 DCHECK(allocator); | 47 DCHECK(allocator); |
| 47 | 48 |
| 48 // If metrics recording is enabled, transfer the allocator to the "release" | 49 // Merge the last deltas from the allocator before it is released. |
| 49 // list. The allocator will continue to live (and keep the associated shared | 50 MergeHistogramDeltasFromAllocator(id, allocator.get()); |
| 50 // memory alive) until the next upload after which it will be released. | |
| 51 // Otherwise, the allocator and its memory will be released when the | |
| 52 // unique_ptr goes out of scope at the end of this method. | |
| 53 if (metrics_recording_enabled_) | |
| 54 allocators_for_exited_processes_.push_back(std::move(allocator)); | |
| 55 } | 51 } |
| 56 | 52 |
| 57 void SubprocessMetricsProvider::OnDidCreateMetricsLog() { | 53 void SubprocessMetricsProvider::MergeHistogramDeltasFromAllocator( |
| 58 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 59 | |
| 60 // The previous reporting cycle is complete and the data used to create it | |
| 61 // will never be needed again. Allocators for exited processes can finally | |
| 62 // be released. | |
| 63 allocators_to_release_.clear(); | |
| 64 } | |
| 65 | |
| 66 void SubprocessMetricsProvider::OnRecordingEnabled() { | |
| 67 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 68 | |
| 69 metrics_recording_enabled_ = true; | |
| 70 } | |
| 71 | |
| 72 void SubprocessMetricsProvider::OnRecordingDisabled() { | |
| 73 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 74 | |
| 75 metrics_recording_enabled_ = false; | |
| 76 allocators_for_exited_processes_.clear(); | |
| 77 allocators_to_release_.clear(); | |
| 78 } | |
| 79 | |
| 80 void SubprocessMetricsProvider::RecordHistogramSnapshotsFromAllocator( | |
| 81 base::HistogramSnapshotManager* snapshot_manager, | |
| 82 int id, | 54 int id, |
| 83 base::PersistentHistogramAllocator* allocator) { | 55 base::PersistentHistogramAllocator* allocator) { |
| 84 DCHECK(allocator); | 56 DCHECK(allocator); |
| 85 | 57 |
| 86 int histogram_count = 0; | 58 int histogram_count = 0; |
| 87 base::PersistentHistogramAllocator::Iterator hist_iter(allocator); | 59 base::PersistentHistogramAllocator::Iterator hist_iter(allocator); |
| 88 while (true) { | 60 while (true) { |
| 89 std::unique_ptr<base::HistogramBase> histogram = hist_iter.GetNext(); | 61 std::unique_ptr<base::HistogramBase> histogram = hist_iter.GetNext(); |
| 90 if (!histogram) | 62 if (!histogram) |
| 91 break; | 63 break; |
| 92 snapshot_manager->PrepareDeltaTakingOwnership(std::move(histogram)); | 64 allocator->MergeHistogramToStatisticsRecorder(histogram.get()); |
| 93 ++histogram_count; | 65 ++histogram_count; |
| 94 } | 66 } |
| 95 | 67 |
| 96 DVLOG(1) << "Reported " << histogram_count << " histograms from subprocess #" | 68 DVLOG(1) << "Reported " << histogram_count << " histograms from subprocess #" |
| 97 << id; | 69 << id; |
| 98 } | 70 } |
| 99 | 71 |
| 100 void SubprocessMetricsProvider::RecordHistogramSnapshots( | 72 void SubprocessMetricsProvider::MergeHistogramDeltas() { |
| 101 base::HistogramSnapshotManager* snapshot_manager) { | |
| 102 DCHECK(thread_checker_.CalledOnValidThread()); | 73 DCHECK(thread_checker_.CalledOnValidThread()); |
| 103 | 74 |
| 104 for (AllocatorByIdMap::iterator iter(&allocators_by_id_); !iter.IsAtEnd(); | 75 for (AllocatorByIdMap::iterator iter(&allocators_by_id_); !iter.IsAtEnd(); |
| 105 iter.Advance()) { | 76 iter.Advance()) { |
| 106 RecordHistogramSnapshotsFromAllocator( | 77 MergeHistogramDeltasFromAllocator(iter.GetCurrentKey(), |
| 107 snapshot_manager, iter.GetCurrentKey(), iter.GetCurrentValue()); | 78 iter.GetCurrentValue()); |
| 108 } | 79 } |
| 109 | 80 |
| 110 for (auto& allocator : allocators_for_exited_processes_) | |
| 111 RecordHistogramSnapshotsFromAllocator(snapshot_manager, 0, allocator.get()); | |
| 112 | |
| 113 UMA_HISTOGRAM_COUNTS_100( | 81 UMA_HISTOGRAM_COUNTS_100( |
| 114 "UMA.SubprocessMetricsProvider.SubprocessCount", | 82 "UMA.SubprocessMetricsProvider.SubprocessCount", |
| 115 allocators_by_id_.size() + allocators_for_exited_processes_.size()); | 83 allocators_by_id_.size()); |
| 116 | |
| 117 // Move allocators for exited processes (which just had final reporting done | |
| 118 // for them) to the queue for being released. The actual release is delayed | |
| 119 // until after reporting is complete so as to not destruct objects that may | |
| 120 // still be needed. | |
| 121 DCHECK(allocators_to_release_.empty()); | |
| 122 allocators_to_release_.swap(allocators_for_exited_processes_); | |
| 123 } | 84 } |
| 124 | 85 |
| 125 void SubprocessMetricsProvider::Observe( | 86 void SubprocessMetricsProvider::Observe( |
| 126 int type, | 87 int type, |
| 127 const content::NotificationSource& source, | 88 const content::NotificationSource& source, |
| 128 const content::NotificationDetails& details) { | 89 const content::NotificationDetails& details) { |
| 129 DCHECK(thread_checker_.CalledOnValidThread()); | 90 DCHECK(thread_checker_.CalledOnValidThread()); |
| 130 DCHECK_EQ(content::NOTIFICATION_RENDERER_PROCESS_CREATED, type); | 91 DCHECK_EQ(content::NOTIFICATION_RENDERER_PROCESS_CREATED, type); |
| 131 | 92 |
| 132 content::RenderProcessHost* host = | 93 content::RenderProcessHost* host = |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 167 content::RenderProcessHost* host) { | 128 content::RenderProcessHost* host) { |
| 168 DCHECK(thread_checker_.CalledOnValidThread()); | 129 DCHECK(thread_checker_.CalledOnValidThread()); |
| 169 | 130 |
| 170 // It's possible for a Renderer to terminate without RenderProcessExited | 131 // It's possible for a Renderer to terminate without RenderProcessExited |
| 171 // (above) being called so it's necessary to de-register also upon the | 132 // (above) being called so it's necessary to de-register also upon the |
| 172 // destruction of the host. If both get called, no harm is done. | 133 // destruction of the host. If both get called, no harm is done. |
| 173 | 134 |
| 174 DeregisterSubprocessAllocator(host->GetID()); | 135 DeregisterSubprocessAllocator(host->GetID()); |
| 175 scoped_observer_.Remove(host); | 136 scoped_observer_.Remove(host); |
| 176 } | 137 } |
| OLD | NEW |