diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2020-10-12 14:27:29 +0200 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2020-10-13 09:35:20 +0000 |
commit | c30a6232df03e1efbd9f3b226777b07e087a1122 (patch) | |
tree | e992f45784689f373bcc38d1b79a239ebe17ee23 /chromium/components/metrics/content | |
parent | 7b5b123ac58f58ffde0f4f6e488bcd09aa4decd3 (diff) | |
download | qtwebengine-chromium-85-based.tar.gz |
BASELINE: Update Chromium to 85.0.4183.14085-based
Change-Id: Iaa42f4680837c57725b1344f108c0196741f6057
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'chromium/components/metrics/content')
8 files changed, 603 insertions, 0 deletions
diff --git a/chromium/components/metrics/content/DEPS b/chromium/components/metrics/content/DEPS new file mode 100644 index 00000000000..c2ff8a0af67 --- /dev/null +++ b/chromium/components/metrics/content/DEPS @@ -0,0 +1,4 @@ +include_rules = [ + "+content/public/browser", + "+gpu/config", +] diff --git a/chromium/components/metrics/content/gpu_metrics_provider.cc b/chromium/components/metrics/content/gpu_metrics_provider.cc new file mode 100644 index 00000000000..baa1e770e92 --- /dev/null +++ b/chromium/components/metrics/content/gpu_metrics_provider.cc @@ -0,0 +1,33 @@ +// Copyright 2014 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 "components/metrics/content/gpu_metrics_provider.h" + +#include "content/public/browser/gpu_data_manager.h" +#include "gpu/config/gpu_info.h" +#include "third_party/metrics_proto/system_profile.pb.h" + +namespace metrics { + +GPUMetricsProvider::GPUMetricsProvider() {} + +GPUMetricsProvider::~GPUMetricsProvider() {} + +void GPUMetricsProvider::ProvideSystemProfileMetrics( + SystemProfileProto* system_profile_proto) { + SystemProfileProto::Hardware* hardware = + system_profile_proto->mutable_hardware(); + + const gpu::GPUInfo& gpu_info = + content::GpuDataManager::GetInstance()->GetGPUInfo(); + const gpu::GPUInfo::GPUDevice& active_gpu = gpu_info.active_gpu(); + SystemProfileProto::Hardware::Graphics* gpu = hardware->mutable_gpu(); + gpu->set_vendor_id(active_gpu.vendor_id); + gpu->set_device_id(active_gpu.device_id); + gpu->set_driver_version(active_gpu.driver_version); + gpu->set_gl_vendor(gpu_info.gl_vendor); + gpu->set_gl_renderer(gpu_info.gl_renderer); +} + +} // namespace metrics diff --git a/chromium/components/metrics/content/gpu_metrics_provider.h b/chromium/components/metrics/content/gpu_metrics_provider.h new file mode 100644 index 00000000000..d429be83cf5 --- /dev/null +++ b/chromium/components/metrics/content/gpu_metrics_provider.h @@ -0,0 +1,29 @@ +// Copyright 2014 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. + +#ifndef COMPONENTS_METRICS_CONTENT_GPU_METRICS_PROVIDER_H_ +#define COMPONENTS_METRICS_CONTENT_GPU_METRICS_PROVIDER_H_ + +#include "base/macros.h" +#include "components/metrics/metrics_provider.h" + +namespace metrics { + +// GPUMetricsProvider provides GPU-related metrics. +class GPUMetricsProvider : public MetricsProvider { + public: + GPUMetricsProvider(); + ~GPUMetricsProvider() override; + + // MetricsProvider: + void ProvideSystemProfileMetrics( + SystemProfileProto* system_profile_proto) override; + + private: + DISALLOW_COPY_AND_ASSIGN(GPUMetricsProvider); +}; + +} // namespace metrics + +#endif // COMPONENTS_METRICS_CONTENT_GPU_METRICS_PROVIDER_H_ diff --git a/chromium/components/metrics/content/rendering_perf_metrics_provider.cc b/chromium/components/metrics/content/rendering_perf_metrics_provider.cc new file mode 100644 index 00000000000..c914f38df01 --- /dev/null +++ b/chromium/components/metrics/content/rendering_perf_metrics_provider.cc @@ -0,0 +1,20 @@ +// Copyright 2020 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 "components/metrics/content/rendering_perf_metrics_provider.h" + +#include "gpu/config/gpu_util.h" + +namespace metrics { + +RenderingPerfMetricsProvider::RenderingPerfMetricsProvider() = default; + +RenderingPerfMetricsProvider::~RenderingPerfMetricsProvider() = default; + +void RenderingPerfMetricsProvider::ProvideCurrentSessionData( + ChromeUserMetricsExtension* uma_proto) { + gpu::RecordDevicePerfInfoHistograms(); +} + +} // namespace metrics diff --git a/chromium/components/metrics/content/rendering_perf_metrics_provider.h b/chromium/components/metrics/content/rendering_perf_metrics_provider.h new file mode 100644 index 00000000000..90ac73b02c2 --- /dev/null +++ b/chromium/components/metrics/content/rendering_perf_metrics_provider.h @@ -0,0 +1,30 @@ +// Copyright 2020 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. + +#ifndef COMPONENTS_METRICS_CONTENT_RENDERING_PERF_METRICS_PROVIDER_H_ +#define COMPONENTS_METRICS_CONTENT_RENDERING_PERF_METRICS_PROVIDER_H_ + +#include "base/macros.h" +#include "components/metrics/metrics_provider.h" + +namespace metrics { + +// RenderingPerfMetricsProvider provides metrics related to rendering +// performance. +class RenderingPerfMetricsProvider : public MetricsProvider { + public: + RenderingPerfMetricsProvider(); + ~RenderingPerfMetricsProvider() override; + + // MetricsProvider: + void ProvideCurrentSessionData( + metrics::ChromeUserMetricsExtension* uma_proto) override; + + private: + DISALLOW_COPY_AND_ASSIGN(RenderingPerfMetricsProvider); +}; + +} // namespace metrics + +#endif // COMPONENTS_METRICS_CONTENT_RENDERING_PERF_METRICS_PROVIDER_H_ diff --git a/chromium/components/metrics/content/subprocess_metrics_provider.cc b/chromium/components/metrics/content/subprocess_metrics_provider.cc new file mode 100644 index 00000000000..9af900d3421 --- /dev/null +++ b/chromium/components/metrics/content/subprocess_metrics_provider.cc @@ -0,0 +1,210 @@ +// 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 "components/metrics/content/subprocess_metrics_provider.h" + +#include <utility> + +#include "base/bind.h" +#include "base/logging.h" +#include "base/metrics/histogram_base.h" +#include "base/metrics/histogram_macros.h" +#include "base/metrics/persistent_histogram_allocator.h" +#include "base/metrics/persistent_memory_allocator.h" +#include "components/metrics/metrics_service.h" +#include "content/public/browser/browser_child_process_host.h" +#include "content/public/browser/browser_task_traits.h" +#include "content/public/browser/browser_thread.h" +#include "content/public/browser/child_process_data.h" + +namespace metrics { +namespace { + +// This is used by tests that don't have an easy way to access the global +// instance of this class. +SubprocessMetricsProvider* g_subprocess_metrics_provider_for_testing; + +} // namespace + +SubprocessMetricsProvider::SubprocessMetricsProvider() { + base::StatisticsRecorder::RegisterHistogramProvider( + weak_ptr_factory_.GetWeakPtr()); + content::BrowserChildProcessObserver::Add(this); + g_subprocess_metrics_provider_for_testing = this; +} + +SubprocessMetricsProvider::~SubprocessMetricsProvider() { + // Safe even if this object has never been added as an observer. + content::BrowserChildProcessObserver::Remove(this); + g_subprocess_metrics_provider_for_testing = nullptr; +} + +// static +void SubprocessMetricsProvider::MergeHistogramDeltasForTesting() { + DCHECK(g_subprocess_metrics_provider_for_testing); + g_subprocess_metrics_provider_for_testing->MergeHistogramDeltas(); +} + +void SubprocessMetricsProvider::RegisterSubprocessAllocator( + int id, + std::unique_ptr<base::PersistentHistogramAllocator> allocator) { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + DCHECK(!allocators_by_id_.Lookup(id)); + + // Stop now if this was called without an allocator, typically because + // GetSubprocessHistogramAllocatorOnIOThread exited early and returned + // null. + if (!allocator) + return; + + // Map is "MapOwnPointer" so transfer ownership to it. + allocators_by_id_.AddWithID(std::move(allocator), id); +} + +void SubprocessMetricsProvider::DeregisterSubprocessAllocator(int id) { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + + if (!allocators_by_id_.Lookup(id)) + return; + + // Extract the matching allocator from the list of active ones. It will + // be automatically released when this method exits. + std::unique_ptr<base::PersistentHistogramAllocator> allocator( + allocators_by_id_.Replace(id, nullptr)); + allocators_by_id_.Remove(id); + DCHECK(allocator); + + // Merge the last deltas from the allocator before it is released. + MergeHistogramDeltasFromAllocator(id, allocator.get()); +} + +void SubprocessMetricsProvider::MergeHistogramDeltasFromAllocator( + int id, + base::PersistentHistogramAllocator* allocator) { + DCHECK(allocator); + + int histogram_count = 0; + base::PersistentHistogramAllocator::Iterator hist_iter(allocator); + while (true) { + std::unique_ptr<base::HistogramBase> histogram = hist_iter.GetNext(); + if (!histogram) + break; + allocator->MergeHistogramDeltaToStatisticsRecorder(histogram.get()); + ++histogram_count; + } + + DVLOG(1) << "Reported " << histogram_count << " histograms from subprocess #" + << id; +} + +void SubprocessMetricsProvider::MergeHistogramDeltas() { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + + for (AllocatorByIdMap::iterator iter(&allocators_by_id_); !iter.IsAtEnd(); + iter.Advance()) { + MergeHistogramDeltasFromAllocator(iter.GetCurrentKey(), + iter.GetCurrentValue()); + } +} + +void SubprocessMetricsProvider::BrowserChildProcessHostConnected( + const content::ChildProcessData& data) { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + + // It's necessary to access the BrowserChildProcessHost object that is + // managing the child in order to extract the metrics memory from it. + // Unfortunately, the required lookup can only be performed on the IO + // thread so do the necessary dance. + content::GetIOThreadTaskRunner({})->PostTaskAndReplyWithResult( + FROM_HERE, + base::BindOnce( + &SubprocessMetricsProvider::GetSubprocessHistogramAllocatorOnIOThread, + data.id), + base::BindOnce(&SubprocessMetricsProvider::RegisterSubprocessAllocator, + weak_ptr_factory_.GetWeakPtr(), data.id)); +} + +void SubprocessMetricsProvider::BrowserChildProcessHostDisconnected( + const content::ChildProcessData& data) { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + DeregisterSubprocessAllocator(data.id); +} + +void SubprocessMetricsProvider::BrowserChildProcessCrashed( + const content::ChildProcessData& data, + const content::ChildProcessTerminationInfo& info) { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + DeregisterSubprocessAllocator(data.id); +} + +void SubprocessMetricsProvider::BrowserChildProcessKilled( + const content::ChildProcessData& data, + const content::ChildProcessTerminationInfo& info) { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + DeregisterSubprocessAllocator(data.id); +} + +void SubprocessMetricsProvider::OnRenderProcessHostCreated( + content::RenderProcessHost* host) { + // 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_CALLED_ON_VALID_THREAD(thread_checker_); + + // If the render-process-host passed a persistent-memory-allocator to the + // renderer process, extract it and register it here. + std::unique_ptr<base::PersistentMemoryAllocator> allocator = + host->TakeMetricsAllocator(); + if (allocator) { + RegisterSubprocessAllocator( + host->GetID(), std::make_unique<base::PersistentHistogramAllocator>( + std::move(allocator))); + } +} + +void SubprocessMetricsProvider::RenderProcessExited( + content::RenderProcessHost* host, + const content::ChildProcessTerminationInfo& info) { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + + DeregisterSubprocessAllocator(host->GetID()); +} + +void SubprocessMetricsProvider::RenderProcessHostDestroyed( + content::RenderProcessHost* host) { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + + // It's possible for a Renderer to terminate without RenderProcessExited + // (above) being called so it's necessary to de-register also upon the + // destruction of the host. If both get called, no harm is done. + + DeregisterSubprocessAllocator(host->GetID()); + scoped_observer_.Remove(host); +} + +// static +std::unique_ptr<base::PersistentHistogramAllocator> +SubprocessMetricsProvider::GetSubprocessHistogramAllocatorOnIOThread(int id) { + // See if the new process has a memory allocator and take control of it if so. + // This call can only be made on the browser's IO thread. + content::BrowserChildProcessHost* host = + content::BrowserChildProcessHost::FromID(id); + if (!host) + return nullptr; + + std::unique_ptr<base::PersistentMemoryAllocator> allocator = + host->TakeMetricsAllocator(); + if (!allocator) + return nullptr; + + return std::make_unique<base::PersistentHistogramAllocator>( + std::move(allocator)); +} + +} // namespace metrics diff --git a/chromium/components/metrics/content/subprocess_metrics_provider.h b/chromium/components/metrics/content/subprocess_metrics_provider.h new file mode 100644 index 00000000000..cac37d5ca47 --- /dev/null +++ b/chromium/components/metrics/content/subprocess_metrics_provider.h @@ -0,0 +1,116 @@ +// 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. + +#ifndef COMPONENTS_METRICS_CONTENT_SUBPROCESS_METRICS_PROVIDER_H_ +#define COMPONENTS_METRICS_CONTENT_SUBPROCESS_METRICS_PROVIDER_H_ + +#include <memory> +#include <set> + +#include "base/containers/id_map.h" +#include "base/gtest_prod_util.h" +#include "base/memory/weak_ptr.h" +#include "base/metrics/statistics_recorder.h" +#include "base/scoped_observer.h" +#include "base/threading/thread_checker.h" +#include "components/metrics/metrics_provider.h" +#include "content/public/browser/browser_child_process_observer.h" +#include "content/public/browser/render_process_host.h" +#include "content/public/browser/render_process_host_creation_observer.h" +#include "content/public/browser/render_process_host_observer.h" + +namespace base { +class PersistentHistogramAllocator; +} + +namespace metrics { + +// SubprocessMetricsProvider gathers and merges histograms stored in shared +// memory segments between processes. Merging occurs when a process exits, +// when metrics are being collected for upload, or when something else needs +// combined metrics (such as the chrome://histograms page). +class SubprocessMetricsProvider + : public MetricsProvider, + public base::StatisticsRecorder::HistogramProvider, + public content::BrowserChildProcessObserver, + public content::RenderProcessHostCreationObserver, + public content::RenderProcessHostObserver { + public: + SubprocessMetricsProvider(); + ~SubprocessMetricsProvider() override; + + // Merge histograms for all subprocesses. This is used by tests that don't + // have access to the internal instance of this class. + static void MergeHistogramDeltasForTesting(); + + private: + friend class SubprocessMetricsProviderTest; + + // Indicates subprocess to be monitored with unique id for later reference. + // Metrics reporting will read histograms from it and upload them to UMA. + void RegisterSubprocessAllocator( + int id, + std::unique_ptr<base::PersistentHistogramAllocator> allocator); + + // Indicates that a subprocess has exited and is thus finished with the + // allocator it was using. + void DeregisterSubprocessAllocator(int id); + + // Merge all histograms of a given allocator to the global StatisticsRecorder. + // This is called periodically during UMA metrics collection (if enabled) and + // possibly on-demand for other purposes. + void MergeHistogramDeltasFromAllocator( + int id, + base::PersistentHistogramAllocator* allocator); + + // MetricsProvider: + void MergeHistogramDeltas() override; + + // content::BrowserChildProcessObserver: + void BrowserChildProcessHostConnected( + const content::ChildProcessData& data) override; + void BrowserChildProcessHostDisconnected( + const content::ChildProcessData& data) override; + void BrowserChildProcessCrashed( + const content::ChildProcessData& data, + const content::ChildProcessTerminationInfo& info) override; + void BrowserChildProcessKilled( + const content::ChildProcessData& data, + const content::ChildProcessTerminationInfo& info) override; + + // content::RenderProcessHostCreationObserver: + void OnRenderProcessHostCreated( + content::RenderProcessHost* process_host) override; + + // content::RenderProcessHostObserver: + void RenderProcessReady(content::RenderProcessHost* host) override; + void RenderProcessExited( + content::RenderProcessHost* host, + const content::ChildProcessTerminationInfo& info) override; + void RenderProcessHostDestroyed(content::RenderProcessHost* host) override; + + // Gets a histogram allocator from a subprocess. This must be called on + // the IO thread. + static std::unique_ptr<base::PersistentHistogramAllocator> + GetSubprocessHistogramAllocatorOnIOThread(int id); + + THREAD_CHECKER(thread_checker_); + + // All of the shared-persistent-allocators for known sub-processes. + using AllocatorByIdMap = + base::IDMap<std::unique_ptr<base::PersistentHistogramAllocator>, int>; + AllocatorByIdMap allocators_by_id_; + + // Track all observed render processes to un-observe them on exit. + ScopedObserver<content::RenderProcessHost, content::RenderProcessHostObserver> + scoped_observer_{this}; + + base::WeakPtrFactory<SubprocessMetricsProvider> weak_ptr_factory_{this}; + + DISALLOW_COPY_AND_ASSIGN(SubprocessMetricsProvider); +}; + +} // namespace metrics + +#endif // COMPONENTS_METRICS_CONTENT_SUBPROCESS_METRICS_PROVIDER_H_ diff --git a/chromium/components/metrics/content/subprocess_metrics_provider_unittest.cc b/chromium/components/metrics/content/subprocess_metrics_provider_unittest.cc new file mode 100644 index 00000000000..26a3a6e640e --- /dev/null +++ b/chromium/components/metrics/content/subprocess_metrics_provider_unittest.cc @@ -0,0 +1,161 @@ +// 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 "components/metrics/content/subprocess_metrics_provider.h" + +#include <memory> +#include <string> +#include <vector> + +#include "base/metrics/histogram.h" +#include "base/metrics/histogram_flattener.h" +#include "base/metrics/histogram_snapshot_manager.h" +#include "base/metrics/persistent_histogram_allocator.h" +#include "base/metrics/persistent_memory_allocator.h" +#include "base/metrics/statistics_recorder.h" +#include "content/public/test/browser_task_environment.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +using ::testing::IsEmpty; +using ::testing::UnorderedElementsAre; + +namespace metrics { +namespace { + +const uint32_t TEST_MEMORY_SIZE = 64 << 10; // 64 KiB + +class HistogramFlattenerDeltaRecorder : public base::HistogramFlattener { + public: + HistogramFlattenerDeltaRecorder() {} + + void RecordDelta(const base::HistogramBase& histogram, + const base::HistogramSamples& snapshot) override { + recorded_delta_histogram_names_.push_back(histogram.histogram_name()); + } + + std::vector<std::string> GetRecordedDeltaHistogramNames() { + return recorded_delta_histogram_names_; + } + + private: + std::vector<std::string> recorded_delta_histogram_names_; + + DISALLOW_COPY_AND_ASSIGN(HistogramFlattenerDeltaRecorder); +}; + +} // namespace + +class SubprocessMetricsProviderTest : public testing::Test { + protected: + SubprocessMetricsProviderTest() { + // MergeHistogramDeltas needs to be called beause it uses a histogram + // macro which caches a pointer to a histogram. If not done before setting + // a persistent global allocator, then it would point into memory that + // will go away. + provider_.MergeHistogramDeltas(); + + // Create a dedicated StatisticsRecorder for this test. + test_recorder_ = base::StatisticsRecorder::CreateTemporaryForTesting(); + + // Create a global allocator using a block of memory from the heap. + base::GlobalHistogramAllocator::CreateWithLocalMemory(TEST_MEMORY_SIZE, 0, + ""); + } + + ~SubprocessMetricsProviderTest() override { + base::GlobalHistogramAllocator::ReleaseForTesting(); + } + + SubprocessMetricsProvider* provider() { return &provider_; } + + std::unique_ptr<base::PersistentHistogramAllocator> CreateDuplicateAllocator( + base::PersistentHistogramAllocator* allocator) { + // Just wrap around the data segment in-use by the passed allocator. + return std::make_unique<base::PersistentHistogramAllocator>( + std::make_unique<base::PersistentMemoryAllocator>( + const_cast<void*>(allocator->data()), allocator->length(), 0, 0, + std::string(), false)); + } + + std::vector<std::string> GetSnapshotHistogramNames() { + // Merge the data from the allocator into the StatisticsRecorder. + provider_.MergeHistogramDeltas(); + + // Flatten what is known to see what has changed since the last time. + HistogramFlattenerDeltaRecorder flattener; + base::HistogramSnapshotManager snapshot_manager(&flattener); + // "true" to the begin() includes histograms held in persistent storage. + base::StatisticsRecorder::PrepareDeltas(true, base::Histogram::kNoFlags, + base::Histogram::kNoFlags, + &snapshot_manager); + return flattener.GetRecordedDeltaHistogramNames(); + } + + void EnableRecording() { provider_.OnRecordingEnabled(); } + void DisableRecording() { provider_.OnRecordingDisabled(); } + + void RegisterSubprocessAllocator( + int id, + std::unique_ptr<base::PersistentHistogramAllocator> allocator) { + provider_.RegisterSubprocessAllocator(id, std::move(allocator)); + } + + void DeregisterSubprocessAllocator(int id) { + provider_.DeregisterSubprocessAllocator(id); + } + + private: + // A thread-bundle makes the tests appear on the UI thread, something that is + // checked in methods called from the SubprocessMetricsProvider class under + // test. This must be constructed before the |provider_| field. + content::BrowserTaskEnvironment task_environment_; + + SubprocessMetricsProvider provider_; + std::unique_ptr<base::StatisticsRecorder> test_recorder_; + + DISALLOW_COPY_AND_ASSIGN(SubprocessMetricsProviderTest); +}; + +TEST_F(SubprocessMetricsProviderTest, SnapshotMetrics) { + base::HistogramBase* foo = base::Histogram::FactoryGet("foo", 1, 100, 10, 0); + base::HistogramBase* bar = base::Histogram::FactoryGet("bar", 1, 100, 10, 0); + base::HistogramBase* baz = base::Histogram::FactoryGet("baz", 1, 100, 10, 0); + foo->Add(42); + bar->Add(84); + + // Detach the global allocator but keep it around until this method exits + // so that the memory holding histogram data doesn't get released. Register + // a new allocator that duplicates the global one. + std::unique_ptr<base::GlobalHistogramAllocator> global_allocator( + base::GlobalHistogramAllocator::ReleaseForTesting()); + RegisterSubprocessAllocator(123, + CreateDuplicateAllocator(global_allocator.get())); + + // Recording should find the two histograms created in persistent memory. + EXPECT_THAT(GetSnapshotHistogramNames(), UnorderedElementsAre("foo", "bar")); + + // A second run should have nothing to produce. + EXPECT_THAT(GetSnapshotHistogramNames(), IsEmpty()); + + // Create a new histogram and update existing ones. Should now report 3 items. + baz->Add(1969); + foo->Add(10); + bar->Add(20); + EXPECT_THAT(GetSnapshotHistogramNames(), + UnorderedElementsAre("foo", "bar", "baz")); + + // Ensure that deregistering does a final merge of the data. + foo->Add(10); + bar->Add(20); + DeregisterSubprocessAllocator(123); + EXPECT_THAT(GetSnapshotHistogramNames(), UnorderedElementsAre("foo", "bar")); + + // Further snapshots should be empty even if things have changed. + foo->Add(10); + bar->Add(20); + EXPECT_THAT(GetSnapshotHistogramNames(), IsEmpty()); +} + +} // namespace metrics |