1 // Copyright 2024 The Pigweed Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not 4 // use this file except in compliance with the License. You may obtain a copy of 5 // the License at 6 // 7 // https://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 // License for the specific language governing permissions and limitations under 13 // the License. 14 15 #include "pw_allocator/benchmarks/measurements.h" 16 17 namespace pw::allocator { 18 namespace internal { 19 20 // GenericMeasurement methods 21 GenericMeasurement(metric::Token name)22GenericMeasurement::GenericMeasurement(metric::Token name) : metrics_(name) { 23 metrics_.Add(nanoseconds_); 24 metrics_.Add(fragmentation_); 25 metrics_.Add(largest_); 26 metrics_.Add(failures_); 27 } 28 Update(const BenchmarkSample & data)29void GenericMeasurement::Update(const BenchmarkSample& data) { 30 count_++; 31 32 float mean = nanoseconds_.value(); 33 mean += (data.nanoseconds - mean) / count_; 34 nanoseconds_.Set(mean); 35 36 mean = fragmentation_.value(); 37 mean += (data.fragmentation - mean) / count_; 38 fragmentation_.Set(mean); 39 40 mean = largest_.value(); 41 mean += (data.largest - mean) / count_; 42 largest_.Set(mean); 43 44 if (data.failed) { 45 failures_.Increment(); 46 } 47 } 48 49 } // namespace internal 50 51 // Measurements methods 52 Measurements(metric::Token name)53Measurements::Measurements(metric::Token name) : metrics_(name) { 54 metrics_.Add(metrics_by_count_); 55 metrics_.Add(metrics_by_fragmentation_); 56 metrics_.Add(metrics_by_size_); 57 } 58 AddByCount(Measurement<size_t> & measurement)59void Measurements::AddByCount(Measurement<size_t>& measurement) { 60 metrics_by_count_.Add(measurement.metrics()); 61 by_count_.insert(measurement); 62 } 63 AddByFragmentation(Measurement<float> & measurement)64void Measurements::AddByFragmentation(Measurement<float>& measurement) { 65 metrics_by_fragmentation_.Add(measurement.metrics()); 66 by_fragmentation_.insert(measurement); 67 } 68 AddBySize(Measurement<size_t> & measurement)69void Measurements::AddBySize(Measurement<size_t>& measurement) { 70 metrics_by_size_.Add(measurement.metrics()); 71 by_size_.insert(measurement); 72 } 73 Clear()74void Measurements::Clear() { 75 by_count_.clear(); 76 by_fragmentation_.clear(); 77 by_size_.clear(); 78 } 79 GetByCount(size_t count)80Measurement<size_t>& Measurements::GetByCount(size_t count) { 81 PW_ASSERT(!by_count_.empty()); 82 auto iter = by_count_.upper_bound(count); 83 if (iter != by_count_.begin()) { 84 --iter; 85 } 86 return *iter; 87 } 88 GetByFragmentation(float fragmentation)89Measurement<float>& Measurements::GetByFragmentation(float fragmentation) { 90 PW_ASSERT(!by_fragmentation_.empty()); 91 auto iter = by_fragmentation_.upper_bound(fragmentation); 92 if (iter != by_fragmentation_.begin()) { 93 --iter; 94 } 95 return *iter; 96 } 97 GetBySize(size_t size)98Measurement<size_t>& Measurements::GetBySize(size_t size) { 99 PW_ASSERT(!by_size_.empty()); 100 auto iter = by_size_.upper_bound(size); 101 if (iter != by_size_.begin()) { 102 --iter; 103 } 104 return *iter; 105 } 106 107 // DefaultMeasurements methods 108 DefaultMeasurements(metric::Token name)109DefaultMeasurements::DefaultMeasurements(metric::Token name) 110 : Measurements(name) { 111 for (auto& measurement : by_count_) { 112 AddByCount(measurement); 113 } 114 for (auto& measurement : by_fragmentation_) { 115 AddByFragmentation(measurement); 116 } 117 for (auto& measurement : by_size_) { 118 AddBySize(measurement); 119 } 120 } 121 122 } // namespace pw::allocator 123