OLD | NEW |
---|---|
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 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 "apps/benchmark/measurements.h" | 5 #include "apps/benchmark/measurements.h" |
6 | 6 |
7 #include <algorithm> | |
8 | |
7 namespace benchmark { | 9 namespace benchmark { |
8 namespace { | 10 namespace { |
9 | 11 |
10 bool Match(const Event& event, const EventSpec& spec) { | 12 static bool Match(const Event& event, const EventSpec& spec) { |
11 return event.name == spec.name && event.categories == spec.categories; | 13 return event.name == spec.name && event.categories == spec.categories; |
12 } | 14 } |
13 | 15 |
14 } // namespace | 16 } // namespace |
15 | 17 |
16 EventSpec::EventSpec() {} | 18 EventSpec::EventSpec() {} |
17 | 19 |
18 EventSpec::EventSpec(std::string name, std::string categories) | 20 EventSpec::EventSpec(std::string name, std::string categories) |
19 : name(name), categories(categories) {} | 21 : name(name), categories(categories) {} |
20 | 22 |
(...skipping 10 matching lines...) Expand all Loading... | |
31 : type(type), target_event(target_event), second_event(second_event) {} | 33 : type(type), target_event(target_event), second_event(second_event) {} |
32 | 34 |
33 Measurement::~Measurement() {} | 35 Measurement::~Measurement() {} |
34 | 36 |
35 Measurements::Measurements(std::vector<Event> events, | 37 Measurements::Measurements(std::vector<Event> events, |
36 base::TimeTicks time_origin) | 38 base::TimeTicks time_origin) |
37 : events_(events), time_origin_(time_origin) {} | 39 : events_(events), time_origin_(time_origin) {} |
38 | 40 |
39 Measurements::~Measurements() {} | 41 Measurements::~Measurements() {} |
40 | 42 |
41 double Measurements::Measure(const Measurement& measurement) { | 43 double Measurements::Measure(const Measurement& measurement) const { |
42 switch (measurement.type) { | 44 switch (measurement.type) { |
43 case MeasurementType::TIME_UNTIL: | 45 case MeasurementType::TIME_UNTIL: |
44 return TimeUntil(measurement.target_event); | 46 return TimeUntil(measurement.target_event); |
45 case MeasurementType::TIME_BETWEEN: | 47 case MeasurementType::TIME_BETWEEN: |
46 return TimeBetween(measurement.target_event, measurement.second_event); | 48 return TimeBetween(measurement.target_event, measurement.second_event); |
47 case MeasurementType::AVG_DURATION: | 49 case MeasurementType::AVG_DURATION: |
48 return AvgDuration(measurement.target_event); | 50 return AvgDuration(measurement.target_event); |
51 case MeasurementType::PERCENTILE_DURATION: | |
52 return Percentile(measurement.target_event, measurement.param); | |
49 default: | 53 default: |
50 NOTREACHED(); | 54 NOTREACHED(); |
51 return double(); | 55 return double(); |
52 } | 56 } |
53 } | 57 } |
54 | 58 |
55 bool Measurements::EarliestOccurence(const EventSpec& event_spec, | 59 bool Measurements::EarliestOccurence(const EventSpec& event_spec, |
56 base::TimeTicks* earliest) { | 60 base::TimeTicks* earliest) const { |
57 base::TimeTicks result; | 61 base::TimeTicks result; |
58 bool found = false; | 62 bool found = false; |
59 for (const Event& event : events_) { | 63 for (const Event& event : events_) { |
60 if (!Match(event, event_spec)) | 64 if (!Match(event, event_spec)) |
61 continue; | 65 continue; |
62 | 66 |
63 if (found) { | 67 if (found) { |
64 result = std::min(result, event.timestamp); | 68 result = std::min(result, event.timestamp); |
65 } else { | 69 } else { |
66 result = event.timestamp; | 70 result = event.timestamp; |
67 found = true; | 71 found = true; |
68 } | 72 } |
69 } | 73 } |
70 if (!found) | 74 if (!found) |
71 return false; | 75 return false; |
72 *earliest = result; | 76 *earliest = result; |
73 return true; | 77 return true; |
74 } | 78 } |
75 | 79 |
76 double Measurements::TimeUntil(const EventSpec& event_spec) { | 80 double Measurements::TimeUntil(const EventSpec& event_spec) const { |
77 base::TimeTicks earliest; | 81 base::TimeTicks earliest; |
78 if (!EarliestOccurence(event_spec, &earliest)) | 82 if (!EarliestOccurence(event_spec, &earliest)) |
79 return -1.0; | 83 return -1.0; |
80 return (earliest - time_origin_).InMillisecondsF(); | 84 return (earliest - time_origin_).InMillisecondsF(); |
81 } | 85 } |
82 | 86 |
83 double Measurements::TimeBetween(const EventSpec& first_event_spec, | 87 double Measurements::TimeBetween(const EventSpec& first_event_spec, |
84 const EventSpec& second_event_spec) { | 88 const EventSpec& second_event_spec) const { |
85 base::TimeTicks earliest_first_event; | 89 base::TimeTicks earliest_first_event; |
86 if (!EarliestOccurence(first_event_spec, &earliest_first_event)) | 90 if (!EarliestOccurence(first_event_spec, &earliest_first_event)) |
87 return -1.0; | 91 return -1.0; |
88 base::TimeTicks earliest_second_event; | 92 base::TimeTicks earliest_second_event; |
89 if (!EarliestOccurence(second_event_spec, &earliest_second_event)) | 93 if (!EarliestOccurence(second_event_spec, &earliest_second_event)) |
90 return -1.0; | 94 return -1.0; |
91 if (earliest_second_event < earliest_first_event) | 95 if (earliest_second_event < earliest_first_event) |
92 return -1.0; | 96 return -1.0; |
93 return (earliest_second_event - earliest_first_event).InMillisecondsF(); | 97 return (earliest_second_event - earliest_first_event).InMillisecondsF(); |
94 } | 98 } |
95 | 99 |
96 double Measurements::AvgDuration(const EventSpec& event_spec) { | 100 double Measurements::AvgDuration(const EventSpec& event_spec) const { |
97 double sum = 0.0; | 101 double sum = 0.0; |
98 int count = 0; | 102 int count = 0; |
99 for (const Event& event : events_) { | 103 for (const Event& event : events_) { |
100 if (event.type != EventType::COMPLETE) | 104 if (event.type != EventType::COMPLETE) |
101 continue; | 105 continue; |
102 | 106 |
103 if (!Match(event, event_spec)) | 107 if (!Match(event, event_spec)) |
104 continue; | 108 continue; |
105 | 109 |
106 sum += event.duration.InMillisecondsF(); | 110 sum += event.duration.InMillisecondsF(); |
107 count += 1; | 111 count += 1; |
108 } | 112 } |
109 | 113 |
110 if (!count) | 114 if (!count) |
111 return -1.0; | 115 return -1.0; |
112 return sum / count; | 116 return sum / count; |
113 } | 117 } |
114 | 118 |
119 double Measurements::Percentile(const EventSpec& event_spec, | |
120 double percentile) const { | |
121 std::vector<double> durations; | |
122 | |
123 if ((percentile < 0.0) || (percentile > 1.0)) { | |
ppi
2015/10/12 19:19:18
Given that we already ensure that in run_args, I'd
zra
2015/10/12 20:38:19
Done.
| |
124 LOG(ERROR) << "Requested percentile should be between 0 and 1 inclusive"; | |
125 } | |
126 | |
127 for (const Event& event : events_) { | |
128 if (event.type != EventType::COMPLETE) | |
129 continue; | |
130 | |
131 if (!Match(event, event_spec)) | |
132 continue; | |
133 | |
134 durations.push_back(event.duration.InMillisecondsF()); | |
135 } | |
136 if (durations.size() == 0) { | |
137 return -1.0; | |
138 } | |
139 | |
140 size_t index = | |
141 static_cast<size_t>(static_cast<double>(durations.size()) * percentile); | |
ppi
2015/10/12 19:19:19
I'd expect that we want index in the range [0, siz
zra
2015/10/12 20:38:19
You're right. Needed to be more careful here. Chan
ppi
2015/10/12 20:53:54
Why not use the simple formula of percentile * (si
zra
2015/10/12 22:59:33
I think we should follow the "Nearest Rank Method"
ppi
2015/10/12 23:15:20
Ack. Thanks for the reference!
| |
142 std::nth_element(durations.begin(), durations.begin() + index, | |
143 durations.end()); | |
144 return durations[index]; | |
145 } | |
146 | |
115 } // namespace benchmark | 147 } // namespace benchmark |
OLD | NEW |