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

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

Issue 2811713003: Embed a single sample in histogram metadata. (Closed)
Patch Set: rebased Created 3 years, 7 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
« no previous file with comments | « base/metrics/histogram_unittest.cc ('k') | base/metrics/persistent_sample_map.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 "base/metrics/persistent_histogram_allocator.h" 5 #include "base/metrics/persistent_histogram_allocator.h"
6 6
7 #include <memory> 7 #include <memory>
8 8
9 #include "base/atomicops.h" 9 #include "base/atomicops.h"
10 #include "base/files/file_path.h" 10 #include "base/files/file_path.h"
(...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after
233 static constexpr size_t kExpectedInstanceSize = 233 static constexpr size_t kExpectedInstanceSize =
234 40 + 2 * HistogramSamples::Metadata::kExpectedInstanceSize; 234 40 + 2 * HistogramSamples::Metadata::kExpectedInstanceSize;
235 235
236 int32_t histogram_type; 236 int32_t histogram_type;
237 int32_t flags; 237 int32_t flags;
238 int32_t minimum; 238 int32_t minimum;
239 int32_t maximum; 239 int32_t maximum;
240 uint32_t bucket_count; 240 uint32_t bucket_count;
241 PersistentMemoryAllocator::Reference ranges_ref; 241 PersistentMemoryAllocator::Reference ranges_ref;
242 uint32_t ranges_checksum; 242 uint32_t ranges_checksum;
243 PersistentMemoryAllocator::Reference counts_ref; 243 subtle::Atomic32 counts_ref; // PersistentMemoryAllocator::Reference
244 HistogramSamples::Metadata samples_metadata; 244 HistogramSamples::Metadata samples_metadata;
245 HistogramSamples::Metadata logged_metadata; 245 HistogramSamples::Metadata logged_metadata;
246 246
247 // Space for the histogram name will be added during the actual allocation 247 // Space for the histogram name will be added during the actual allocation
248 // request. This must be the last field of the structure. A zero-size array 248 // request. This must be the last field of the structure. A zero-size array
249 // or a "flexible" array would be preferred but is not (yet) valid C++. 249 // or a "flexible" array would be preferred but is not (yet) valid C++.
250 char name[sizeof(uint64_t)]; // Force 64-bit alignment on 32-bit builds. 250 char name[sizeof(uint64_t)]; // Force 64-bit alignment on 32-bit builds.
251 }; 251 };
252 252
253 PersistentHistogramAllocator::Iterator::Iterator( 253 PersistentHistogramAllocator::Iterator::Iterator(
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
368 } else { 368 } else {
369 // This should never happen but be tolerant if it does. 369 // This should never happen but be tolerant if it does.
370 NOTREACHED(); 370 NOTREACHED();
371 ranges_ref = PersistentMemoryAllocator::kReferenceNull; 371 ranges_ref = PersistentMemoryAllocator::kReferenceNull;
372 } 372 }
373 } 373 }
374 } else { 374 } else {
375 DCHECK_EQ(kTypeIdRangesArray, memory_allocator_->GetType(ranges_ref)); 375 DCHECK_EQ(kTypeIdRangesArray, memory_allocator_->GetType(ranges_ref));
376 } 376 }
377 377
378 PersistentMemoryAllocator::Reference counts_ref =
379 memory_allocator_->Allocate(counts_bytes, kTypeIdCountsArray);
380 378
381 // Only continue here if all allocations were successful. If they weren't, 379 // Only continue here if all allocations were successful. If they weren't,
382 // there is no way to free the space but that's not really a problem since 380 // there is no way to free the space but that's not really a problem since
383 // the allocations only fail because the space is full or corrupt and so 381 // the allocations only fail because the space is full or corrupt and so
384 // any future attempts will also fail. 382 // any future attempts will also fail.
385 if (counts_ref && ranges_ref && histogram_data) { 383 if (ranges_ref && histogram_data) {
386 histogram_data->minimum = minimum; 384 histogram_data->minimum = minimum;
387 histogram_data->maximum = maximum; 385 histogram_data->maximum = maximum;
388 // |bucket_count| must fit within 32-bits or the allocation of the counts 386 // |bucket_count| must fit within 32-bits or the allocation of the counts
389 // array would have failed for being too large; the allocator supports 387 // array would have failed for being too large; the allocator supports
390 // less than 4GB total size. 388 // less than 4GB total size.
391 histogram_data->bucket_count = static_cast<uint32_t>(bucket_count); 389 histogram_data->bucket_count = static_cast<uint32_t>(bucket_count);
392 histogram_data->ranges_ref = ranges_ref; 390 histogram_data->ranges_ref = ranges_ref;
393 histogram_data->ranges_checksum = bucket_ranges->checksum(); 391 histogram_data->ranges_checksum = bucket_ranges->checksum();
394 histogram_data->counts_ref = counts_ref;
395 } else { 392 } else {
396 histogram_data = nullptr; // Clear this for proper handling below. 393 histogram_data = nullptr; // Clear this for proper handling below.
397 } 394 }
398 } 395 }
399 396
400 if (histogram_data) { 397 if (histogram_data) {
401 // Create the histogram using resources in persistent memory. This ends up 398 // Create the histogram using resources in persistent memory. This ends up
402 // resolving the "ref" values stored in histogram_data instad of just 399 // resolving the "ref" values stored in histogram_data instad of just
403 // using what is already known above but avoids duplicating the switch 400 // using what is already known above but avoids duplicating the switch
404 // statement here and serves as a double-check that everything is 401 // statement here and serves as a double-check that everything is
(...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after
599 histogram_data.bucket_count + 1); 596 histogram_data.bucket_count + 1);
600 if (!created_ranges) { 597 if (!created_ranges) {
601 RecordCreateHistogramResult(CREATE_HISTOGRAM_INVALID_RANGES_ARRAY); 598 RecordCreateHistogramResult(CREATE_HISTOGRAM_INVALID_RANGES_ARRAY);
602 NOTREACHED(); 599 NOTREACHED();
603 return nullptr; 600 return nullptr;
604 } 601 }
605 const BucketRanges* ranges = 602 const BucketRanges* ranges =
606 StatisticsRecorder::RegisterOrDeleteDuplicateRanges( 603 StatisticsRecorder::RegisterOrDeleteDuplicateRanges(
607 created_ranges.release()); 604 created_ranges.release());
608 605
609 HistogramBase::AtomicCount* counts_data =
610 memory_allocator_->GetAsArray<HistogramBase::AtomicCount>(
611 histogram_data.counts_ref, kTypeIdCountsArray,
612 PersistentMemoryAllocator::kSizeAny);
613 size_t counts_bytes = 606 size_t counts_bytes =
614 CalculateRequiredCountsBytes(histogram_data.bucket_count); 607 CalculateRequiredCountsBytes(histogram_data.bucket_count);
615 if (!counts_data || counts_bytes == 0 || 608 PersistentMemoryAllocator::Reference counts_ref =
616 memory_allocator_->GetAllocSize(histogram_data.counts_ref) < 609 subtle::NoBarrier_Load(&histogram_data.counts_ref);
617 counts_bytes) { 610 if (counts_bytes == 0 ||
611 (counts_ref != 0 &&
612 memory_allocator_->GetAllocSize(counts_ref) < counts_bytes)) {
618 RecordCreateHistogramResult(CREATE_HISTOGRAM_INVALID_COUNTS_ARRAY); 613 RecordCreateHistogramResult(CREATE_HISTOGRAM_INVALID_COUNTS_ARRAY);
619 NOTREACHED(); 614 NOTREACHED();
620 return nullptr; 615 return nullptr;
621 } 616 }
622 617
623 // After the main "counts" array is a second array using for storing what 618 // The "counts" data (including both samples and logged samples) is a delayed
624 // was previously logged. This is used to calculate the "delta" during 619 // persistent allocation meaning that though its size and storage for a
625 // snapshot operations. 620 // reference is defined, no space is reserved until actually needed. When
626 HistogramBase::AtomicCount* logged_data = 621 // it is needed, memory will be allocated from the persistent segment and
627 counts_data + histogram_data.bucket_count; 622 // a reference to it stored at the passed address. Other threads can then
623 // notice the valid reference and access the same data.
624 DelayedPersistentAllocation counts_data(memory_allocator_.get(),
625 &histogram_data_ptr->counts_ref,
626 kTypeIdCountsArray, counts_bytes, 0);
628 627
628 // A second delayed allocations is defined using the same reference storage
629 // location as the first so the allocation of one will automatically be found
630 // by the other. Within the block, the first half of the space is for "counts"
631 // and the second half is for "logged counts".
632 DelayedPersistentAllocation logged_data(
633 memory_allocator_.get(), &histogram_data_ptr->counts_ref,
634 kTypeIdCountsArray, counts_bytes, counts_bytes / 2,
635 /*make_iterable=*/false);
636
637 // Create the right type of histogram.
629 std::string name(histogram_data_ptr->name); 638 std::string name(histogram_data_ptr->name);
630 std::unique_ptr<HistogramBase> histogram; 639 std::unique_ptr<HistogramBase> histogram;
631 switch (histogram_data.histogram_type) { 640 switch (histogram_data.histogram_type) {
632 case HISTOGRAM: 641 case HISTOGRAM:
633 histogram = Histogram::PersistentCreate( 642 histogram = Histogram::PersistentCreate(
634 name, histogram_data.minimum, histogram_data.maximum, ranges, 643 name, histogram_data.minimum, histogram_data.maximum, ranges,
635 counts_data, logged_data, histogram_data.bucket_count, 644 counts_data, logged_data, &histogram_data_ptr->samples_metadata,
636 &histogram_data_ptr->samples_metadata,
637 &histogram_data_ptr->logged_metadata); 645 &histogram_data_ptr->logged_metadata);
638 DCHECK(histogram); 646 DCHECK(histogram);
639 break; 647 break;
640 case LINEAR_HISTOGRAM: 648 case LINEAR_HISTOGRAM:
641 histogram = LinearHistogram::PersistentCreate( 649 histogram = LinearHistogram::PersistentCreate(
642 name, histogram_data.minimum, histogram_data.maximum, ranges, 650 name, histogram_data.minimum, histogram_data.maximum, ranges,
643 counts_data, logged_data, histogram_data.bucket_count, 651 counts_data, logged_data, &histogram_data_ptr->samples_metadata,
644 &histogram_data_ptr->samples_metadata,
645 &histogram_data_ptr->logged_metadata); 652 &histogram_data_ptr->logged_metadata);
646 DCHECK(histogram); 653 DCHECK(histogram);
647 break; 654 break;
648 case BOOLEAN_HISTOGRAM: 655 case BOOLEAN_HISTOGRAM:
649 histogram = BooleanHistogram::PersistentCreate( 656 histogram = BooleanHistogram::PersistentCreate(
650 name, ranges, counts_data, logged_data, 657 name, ranges, counts_data, logged_data,
651 &histogram_data_ptr->samples_metadata, 658 &histogram_data_ptr->samples_metadata,
652 &histogram_data_ptr->logged_metadata); 659 &histogram_data_ptr->logged_metadata);
653 DCHECK(histogram); 660 DCHECK(histogram);
654 break; 661 break;
655 case CUSTOM_HISTOGRAM: 662 case CUSTOM_HISTOGRAM:
656 histogram = CustomHistogram::PersistentCreate( 663 histogram = CustomHistogram::PersistentCreate(
657 name, ranges, counts_data, logged_data, histogram_data.bucket_count, 664 name, ranges, counts_data, logged_data,
658 &histogram_data_ptr->samples_metadata, 665 &histogram_data_ptr->samples_metadata,
659 &histogram_data_ptr->logged_metadata); 666 &histogram_data_ptr->logged_metadata);
660 DCHECK(histogram); 667 DCHECK(histogram);
661 break; 668 break;
662 default: 669 default:
663 NOTREACHED(); 670 NOTREACHED();
664 } 671 }
665 672
666 if (histogram) { 673 if (histogram) {
667 DCHECK_EQ(histogram_data.histogram_type, histogram->GetHistogramType()); 674 DCHECK_EQ(histogram_data.histogram_type, histogram->GetHistogramType());
(...skipping 285 matching lines...) Expand 10 before | Expand all | Expand 10 after
953 while (true) { 960 while (true) {
954 std::unique_ptr<HistogramBase> histogram = 961 std::unique_ptr<HistogramBase> histogram =
955 import_iterator_.GetNextWithIgnore(record_to_ignore); 962 import_iterator_.GetNextWithIgnore(record_to_ignore);
956 if (!histogram) 963 if (!histogram)
957 break; 964 break;
958 StatisticsRecorder::RegisterOrDeleteDuplicate(histogram.release()); 965 StatisticsRecorder::RegisterOrDeleteDuplicate(histogram.release());
959 } 966 }
960 } 967 }
961 968
962 } // namespace base 969 } // namespace base
OLDNEW
« no previous file with comments | « base/metrics/histogram_unittest.cc ('k') | base/metrics/persistent_sample_map.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698