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

Unified Diff: base/metrics/persistent_histogram_allocator.cc

Issue 1840843004: Improve efficiency of persistent sparse histograms. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@improved-pma-iterator
Patch Set: added comment clarifying loop behavior Created 4 years, 8 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « base/metrics/persistent_histogram_allocator.h ('k') | base/metrics/persistent_memory_allocator.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: base/metrics/persistent_histogram_allocator.cc
diff --git a/base/metrics/persistent_histogram_allocator.cc b/base/metrics/persistent_histogram_allocator.cc
index 1d5c0ef0e1c5d90175f8456469b67502f34e1d28..b38c1efa8b720ba123c51712c586b466cadcd097 100644
--- a/base/metrics/persistent_histogram_allocator.cc
+++ b/base/metrics/persistent_histogram_allocator.cc
@@ -12,6 +12,7 @@
#include "base/metrics/histogram.h"
#include "base/metrics/histogram_base.h"
#include "base/metrics/histogram_samples.h"
+#include "base/metrics/persistent_sample_map.h"
#include "base/metrics/sparse_histogram.h"
#include "base/metrics/statistics_recorder.h"
#include "base/synchronization/lock.h"
@@ -91,6 +92,134 @@ const Feature kPersistentHistogramsFeature{
"PersistentHistograms", FEATURE_DISABLED_BY_DEFAULT
};
+
+PersistentSparseHistogramDataManager::PersistentSparseHistogramDataManager(
+ PersistentMemoryAllocator* allocator)
+ : allocator_(allocator), record_iterator_(allocator) {}
+
+PersistentSparseHistogramDataManager::~PersistentSparseHistogramDataManager() {}
+
+PersistentSampleMapRecords*
+PersistentSparseHistogramDataManager::UseSampleMapRecords(uint64_t id,
+ const void* user) {
+ base::AutoLock auto_lock(lock_);
+ return GetSampleMapRecordsWhileLocked(id)->Acquire(user);
+}
+
+PersistentSampleMapRecords*
+PersistentSparseHistogramDataManager::GetSampleMapRecordsWhileLocked(
+ uint64_t id) {
+ lock_.AssertAcquired();
+
+ auto found = sample_records_.find(id);
+ if (found != sample_records_.end())
+ return found->second.get();
+
+ std::unique_ptr<PersistentSampleMapRecords>& samples = sample_records_[id];
+ samples = WrapUnique(new PersistentSampleMapRecords(this, id));
+ return samples.get();
+}
+
+bool PersistentSparseHistogramDataManager::LoadRecords(
+ PersistentSampleMapRecords* sample_map_records) {
+ // DataManager must be locked in order to access the found_ field of any
+ // PersistentSampleMapRecords object.
+ base::AutoLock auto_lock(lock_);
+ bool found = false;
+
+ // If there are already "found" entries for the passed object, move them.
+ if (!sample_map_records->found_.empty()) {
+ sample_map_records->records_.reserve(sample_map_records->records_.size() +
+ sample_map_records->found_.size());
+ sample_map_records->records_.insert(sample_map_records->records_.end(),
+ sample_map_records->found_.begin(),
+ sample_map_records->found_.end());
+ sample_map_records->found_.clear();
+ found = true;
+ }
+
+ // Acquiring a lock is a semi-expensive operation so load some records with
+ // each call. More than this number may be loaded if it takes longer to
+ // find at least one matching record for the passed object.
+ const int kMinimumNumberToLoad = 10;
+ const uint64_t match_id = sample_map_records->sample_map_id_;
+
+ // Loop while no enty is found OR we haven't yet loaded the minimum number.
+ // This will continue reading even after a match is found.
+ for (int count = 0; !found || count < kMinimumNumberToLoad; ++count) {
+ // Get the next sample-record. The iterator will always resume from where
+ // it left off even if it previously had nothing further to return.
+ uint64_t found_id;
+ PersistentMemoryAllocator::Reference ref =
+ PersistentSampleMap::GetNextPersistentRecord(record_iterator_,
+ &found_id);
+
+ // Stop immediately if there are none.
+ if (!ref)
+ break;
+
+ // The sample-record could be for any sparse histogram. Add the reference
+ // to the appropriate collection for later use.
+ if (found_id == match_id) {
+ sample_map_records->records_.push_back(ref);
+ found = true;
+ } else {
+ PersistentSampleMapRecords* samples =
+ GetSampleMapRecordsWhileLocked(found_id);
+ DCHECK(samples);
+ samples->found_.push_back(ref);
+ }
+ }
+
+ return found;
+}
+
+
+PersistentSampleMapRecords::PersistentSampleMapRecords(
+ PersistentSparseHistogramDataManager* data_manager,
+ uint64_t sample_map_id)
+ : data_manager_(data_manager), sample_map_id_(sample_map_id) {}
+
+PersistentSampleMapRecords::~PersistentSampleMapRecords() {}
+
+PersistentSampleMapRecords* PersistentSampleMapRecords::Acquire(
+ const void* user) {
+ DCHECK(!user_);
+ user_ = user;
+ seen_ = 0;
+ return this;
+}
+
+void PersistentSampleMapRecords::Release(const void* user) {
+ DCHECK_EQ(user_, user);
+ user_ = nullptr;
+}
+
+PersistentMemoryAllocator::Reference PersistentSampleMapRecords::GetNext() {
+ DCHECK(user_);
+
+ // If there are no unseen records, lock and swap in all the found ones.
+ if (records_.size() == seen_) {
+ if (!data_manager_->LoadRecords(this))
+ return false;
+ }
+
+ // Return the next record. Records *must* be returned in the same order
+ // they are found in the persistent memory in order to ensure that all
+ // objects using this data always have the same state. Race conditions
+ // can cause duplicate records so using the "first found" is the only
+ // guarantee that all objects always access the same one.
+ DCHECK_LT(seen_, records_.size());
+ return records_[seen_++];
+}
+
+PersistentMemoryAllocator::Reference PersistentSampleMapRecords::CreateNew(
+ HistogramBase::Sample value) {
+ return PersistentSampleMap::CreatePersistentRecord(data_manager_->allocator_,
+ sample_map_id_, value);
+}
+
+
// This data will be held in persistent memory in order for processes to
// locate and use histograms created elsewhere.
struct PersistentHistogramAllocator::PersistentHistogramData {
@@ -125,9 +254,11 @@ PersistentHistogramAllocator::Iterator::GetNextWithIgnore(Reference ignore) {
return nullptr;
}
+
PersistentHistogramAllocator::PersistentHistogramAllocator(
std::unique_ptr<PersistentMemoryAllocator> memory)
- : memory_allocator_(std::move(memory)) {}
+ : memory_allocator_(std::move(memory)),
+ sparse_histogram_data_manager_(memory_allocator_.get()) {}
PersistentHistogramAllocator::~PersistentHistogramAllocator() {}
@@ -196,8 +327,7 @@ std::unique_ptr<HistogramBase> PersistentHistogramAllocator::CreateHistogram(
// Sparse histograms are quite different so handle them as a special case.
if (histogram_data_ptr->histogram_type == SPARSE_HISTOGRAM) {
std::unique_ptr<HistogramBase> histogram =
- SparseHistogram::PersistentCreate(memory_allocator(),
- histogram_data_ptr->name,
+ SparseHistogram::PersistentCreate(this, histogram_data_ptr->name,
&histogram_data_ptr->samples_metadata,
&histogram_data_ptr->logged_metadata);
DCHECK(histogram);
@@ -343,6 +473,12 @@ void PersistentHistogramAllocator::FinalizeHistogram(Reference ref,
memory_allocator_->SetType(ref, 0);
}
+PersistentSampleMapRecords* PersistentHistogramAllocator::UseSampleMapRecords(
+ uint64_t id,
+ const void* user) {
+ return sparse_histogram_data_manager_.UseSampleMapRecords(id, user);
+}
+
std::unique_ptr<HistogramBase> PersistentHistogramAllocator::AllocateHistogram(
HistogramType histogram_type,
const std::string& name,
« no previous file with comments | « base/metrics/persistent_histogram_allocator.h ('k') | base/metrics/persistent_memory_allocator.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698