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

Side by Side Diff: base/metrics/histogram_persistence.cc

Issue 1537743006: Persist setup metrics and have Chrome report them during UMA upload. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@shared-histograms
Patch Set: test needs to clear out statistics-recorder before releasing histogram memory Created 4 years, 10 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) 2015 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2015 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 "base/metrics/histogram_persistence.h" 5 #include "base/metrics/histogram_persistence.h"
6 6
7 #include "base/lazy_instance.h" 7 #include "base/lazy_instance.h"
8 #include "base/logging.h" 8 #include "base/logging.h"
9 #include "base/memory/scoped_ptr.h" 9 #include "base/memory/scoped_ptr.h"
10 #include "base/metrics/histogram.h" 10 #include "base/metrics/histogram.h"
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
43 // Could not allocate histogram memory due to unknown error. 43 // Could not allocate histogram memory due to unknown error.
44 CREATE_HISTOGRAM_ALLOCATOR_ERROR, 44 CREATE_HISTOGRAM_ALLOCATOR_ERROR,
45 45
46 // Histogram was of unknown type. 46 // Histogram was of unknown type.
47 CREATE_HISTOGRAM_UNKNOWN_TYPE, 47 CREATE_HISTOGRAM_UNKNOWN_TYPE,
48 48
49 // Always keep this at the end. 49 // Always keep this at the end.
50 CREATE_HISTOGRAM_MAX 50 CREATE_HISTOGRAM_MAX
51 }; 51 };
52 52
53 // Name of histogram for storing results of local operations.
54 const char kResultHistogram[] = "UMA.CreatePersistentHistogram.Result";
55
53 // Type identifiers used when storing in persistent memory so they can be 56 // Type identifiers used when storing in persistent memory so they can be
54 // identified during extraction; the first 4 bytes of the SHA1 of the name 57 // identified during extraction; the first 4 bytes of the SHA1 of the name
55 // is used as a unique integer. A "version number" is added to the base 58 // is used as a unique integer. A "version number" is added to the base
56 // so that, if the structure of that object changes, stored older versions 59 // so that, if the structure of that object changes, stored older versions
57 // will be safely ignored. 60 // will be safely ignored.
58 enum : uint32_t { 61 enum : uint32_t {
59 kTypeIdHistogram = 0xF1645910 + 1, // SHA1(Histogram) v1 62 kTypeIdHistogram = 0xF1645910 + 1, // SHA1(Histogram) v1
60 kTypeIdRangesArray = 0xBCEA225A + 1, // SHA1(RangesArray) v1 63 kTypeIdRangesArray = 0xBCEA225A + 1, // SHA1(RangesArray) v1
61 kTypeIdCountsArray = 0x53215530 + 1, // SHA1(CountsArray) v1 64 kTypeIdCountsArray = 0x53215530 + 1, // SHA1(CountsArray) v1
62 }; 65 };
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
142 base::subtle::Acquire_Load(&atomic_histogram_pointer))); 145 base::subtle::Acquire_Load(&atomic_histogram_pointer)));
143 if (!histogram_pointer) { 146 if (!histogram_pointer) {
144 // It's possible for multiple threads to make it here in parallel but 147 // It's possible for multiple threads to make it here in parallel but
145 // they'll always return the same result as there is a mutex in the Get. 148 // they'll always return the same result as there is a mutex in the Get.
146 // The purpose of the "initialized" variable is just to ensure that 149 // The purpose of the "initialized" variable is just to ensure that
147 // the same thread doesn't recurse which is also why it doesn't have 150 // the same thread doesn't recurse which is also why it doesn't have
148 // to be atomic. 151 // to be atomic.
149 static bool initialized = false; 152 static bool initialized = false;
150 if (!initialized) { 153 if (!initialized) {
151 initialized = true; 154 initialized = true;
155 if (g_allocator) {
156 DLOG(WARNING) << "Creating the results-histogram inside persistent"
157 << " memory can cause future allocations to crash if"
158 << " that memory is ever released (for testing).";
159 }
160
152 histogram_pointer = LinearHistogram::FactoryGet( 161 histogram_pointer = LinearHistogram::FactoryGet(
153 "UMA.CreatePersistentHistogram.Result", 162 kResultHistogram, 1, CREATE_HISTOGRAM_MAX, CREATE_HISTOGRAM_MAX + 1,
154 1, CREATE_HISTOGRAM_MAX, CREATE_HISTOGRAM_MAX + 1,
155 HistogramBase::kUmaTargetedHistogramFlag); 163 HistogramBase::kUmaTargetedHistogramFlag);
156 base::subtle::Release_Store( 164 base::subtle::Release_Store(
157 &atomic_histogram_pointer, 165 &atomic_histogram_pointer,
158 reinterpret_cast<base::subtle::AtomicWord>(histogram_pointer)); 166 reinterpret_cast<base::subtle::AtomicWord>(histogram_pointer));
159 } 167 }
160 } 168 }
161 return histogram_pointer; 169 return histogram_pointer;
162 } 170 }
163 171
164 // Record the result of a histogram creation. 172 // Record the result of a histogram creation.
165 void RecordCreateHistogramResult(CreateHistogramResultType result) { 173 void RecordCreateHistogramResult(CreateHistogramResultType result) {
166 HistogramBase* result_histogram = GetCreateHistogramResultHistogram(); 174 HistogramBase* result_histogram = GetCreateHistogramResultHistogram();
167 if (result_histogram) 175 if (result_histogram)
168 result_histogram->Add(result); 176 result_histogram->Add(result);
169 } 177 }
170 178
171 void SetPersistentHistogramMemoryAllocator( 179 void SetPersistentHistogramMemoryAllocator(
172 PersistentMemoryAllocator* allocator) { 180 PersistentMemoryAllocator* allocator) {
173 // Releasing or changing an allocator is extremely dangerous because it 181 // Releasing or changing an allocator is extremely dangerous because it
174 // likely has histograms stored within it. If the backing memory is also 182 // likely has histograms stored within it. If the backing memory is also
175 // also released, future accesses to those histograms will seg-fault. 183 // also released, future accesses to those histograms will seg-fault.
176 // It's not a fatal CHECK() because tests do this knowing that all 184 CHECK(!g_allocator);
177 // such persistent histograms have already been forgotten.
178 if (g_allocator) {
179 LOG(WARNING) << "Active PersistentMemoryAllocator has been released."
180 << " Some existing histogram pointers may be invalid.";
181 delete g_allocator;
182 }
183 g_allocator = allocator; 185 g_allocator = allocator;
184 } 186 }
185 187
186 PersistentMemoryAllocator* GetPersistentHistogramMemoryAllocator() { 188 PersistentMemoryAllocator* GetPersistentHistogramMemoryAllocator() {
187 return g_allocator; 189 return g_allocator;
188 } 190 }
189 191
190 PersistentMemoryAllocator* ReleasePersistentHistogramMemoryAllocator() { 192 PersistentMemoryAllocator*
193 ReleasePersistentHistogramMemoryAllocatorForTesting() {
191 PersistentMemoryAllocator* allocator = g_allocator; 194 PersistentMemoryAllocator* allocator = g_allocator;
195 if (!allocator)
196 return nullptr;
197
198 // Before releasing the memory, it's necessary to have the Statistics
199 // Recorder forget about the histograms contained within otherwise some
200 // operations will try to access it.
201 PersistentMemoryAllocator::Iterator iter;
202 PersistentMemoryAllocator::Reference ref;
203 uint32_t type_id;
204 allocator->CreateIterator(&iter);
205 while ((ref = allocator->GetNextIterable(&iter, &type_id)) != 0) {
206 if (type_id == kTypeIdHistogram) {
207 PersistentHistogramData* histogram_data =
208 allocator->GetAsObject<PersistentHistogramData>(
209 ref, kTypeIdHistogram);
210 DCHECK(histogram_data);
211 std::string name(histogram_data->name);
212 StatisticsRecorder::ForgetHistogramForTesting(name);
213 DLOG(WARNING) << "Dropped persistent histogram \"" << name << "\"";
214
215 // Fix by calling GetCreateHistogramResultHistogram() before setting
216 // the (temporary) persistent memory allocator.
217 DCHECK_NE(kResultHistogram, name);
218 }
219 }
220
192 g_allocator = nullptr; 221 g_allocator = nullptr;
193 return allocator; 222 return allocator;
194 }; 223 };
195 224
196 HistogramBase* CreatePersistentHistogram( 225 HistogramBase* CreatePersistentHistogram(
197 PersistentMemoryAllocator* allocator, 226 PersistentMemoryAllocator* allocator,
198 PersistentHistogramData* histogram_data_ptr) { 227 PersistentHistogramData* histogram_data_ptr) {
199 if (!histogram_data_ptr) { 228 if (!histogram_data_ptr) {
200 RecordCreateHistogramResult(CREATE_HISTOGRAM_INVALID_METADATA_POINTER); 229 RecordCreateHistogramResult(CREATE_HISTOGRAM_INVALID_METADATA_POINTER);
201 NOTREACHED(); 230 NOTREACHED();
(...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after
437 } 466 }
438 RecordCreateHistogramResult(result); 467 RecordCreateHistogramResult(result);
439 NOTREACHED() << "error=" << result; 468 NOTREACHED() << "error=" << result;
440 469
441 return nullptr; 470 return nullptr;
442 } 471 }
443 472
444 void ImportPersistentHistograms() { 473 void ImportPersistentHistograms() {
445 // The lock protects against concurrent access to the iterator and is created 474 // The lock protects against concurrent access to the iterator and is created
446 // in a thread-safe manner when needed. 475 // in a thread-safe manner when needed.
447 static base::LazyInstance<base::Lock> lock = LAZY_INSTANCE_INITIALIZER; 476 static base::LazyInstance<base::Lock>::Leaky lock = LAZY_INSTANCE_INITIALIZER;
448 477
449 if (g_allocator) { 478 if (g_allocator) {
450 base::AutoLock auto_lock(lock.Get()); 479 base::AutoLock auto_lock(lock.Get());
451 480
452 // Each call resumes from where it last left off so need persistant 481 // Each call resumes from where it last left off so need persistant
453 // iterator. This class has a constructor so even the definition has 482 // iterator. This class has a constructor so even the definition has
454 // to be protected by the lock in order to be thread-safe. 483 // to be protected by the lock in order to be thread-safe.
455 static PersistentMemoryAllocator::Iterator iter; 484 static PersistentMemoryAllocator::Iterator iter;
456 if (iter.is_clear()) 485 if (iter.is_clear())
457 g_allocator->CreateIterator(&iter); 486 g_allocator->CreateIterator(&iter);
458 487
459 for (;;) { 488 for (;;) {
grt (UTC plus 2) 2016/02/15 15:42:39 fyi for the future: "while (true)" is more common
bcwhite 2016/02/15 19:22:10 Done.
460 HistogramBase* histogram = GetNextPersistentHistogram(g_allocator, &iter); 489 HistogramBase* histogram = GetNextPersistentHistogram(g_allocator, &iter);
461 if (!histogram) 490 if (!histogram)
462 break; 491 break;
463 StatisticsRecorder::RegisterOrDeleteDuplicate(histogram); 492 StatisticsRecorder::RegisterOrDeleteDuplicate(histogram);
464 } 493 }
465 } 494 }
466 } 495 }
467 496
468 } // namespace base 497 } // namespace base
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698