1 /*
2 * Copyright (C) 2018 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 #include <vector>
17
18 #include "FieldValue.h"
19 #include "HashableDimensionKey.h"
20 #include "benchmark/benchmark.h"
21 #include "logd/LogEvent.h"
22 #include "stats_log_util.h"
23 #include "tests/statsd_test_util.h"
24
25 namespace android {
26 namespace os {
27 namespace statsd {
28
29 using std::vector;
30
CreateDurationMetricConfig_NoLink_AND_CombinationCondition(DurationMetric::AggregationType aggregationType,bool addExtraDimensionInCondition)31 static StatsdConfig CreateDurationMetricConfig_NoLink_AND_CombinationCondition(
32 DurationMetric::AggregationType aggregationType, bool addExtraDimensionInCondition) {
33 StatsdConfig config;
34 *config.add_atom_matcher() = CreateStartScheduledJobAtomMatcher();
35 *config.add_atom_matcher() = CreateFinishScheduledJobAtomMatcher();
36 *config.add_atom_matcher() = CreateSyncStartAtomMatcher();
37 *config.add_atom_matcher() = CreateSyncEndAtomMatcher();
38 *config.add_atom_matcher() = CreateScreenTurnedOnAtomMatcher();
39 *config.add_atom_matcher() = CreateScreenTurnedOffAtomMatcher();
40
41 auto scheduledJobPredicate = CreateScheduledJobPredicate();
42 auto dimensions = scheduledJobPredicate.mutable_simple_predicate()->mutable_dimensions();
43 dimensions->set_field(util::SCHEDULED_JOB_STATE_CHANGED);
44 dimensions->add_child()->set_field(2); // job name field.
45
46 auto screenIsOffPredicate = CreateScreenIsOffPredicate();
47
48 auto isSyncingPredicate = CreateIsSyncingPredicate();
49 auto syncDimension = isSyncingPredicate.mutable_simple_predicate()->mutable_dimensions();
50 *syncDimension =
51 CreateAttributionUidAndTagDimensions(util::SYNC_STATE_CHANGED, {Position::FIRST});
52 if (addExtraDimensionInCondition) {
53 syncDimension->add_child()->set_field(2 /* name field*/);
54 }
55
56 *config.add_predicate() = scheduledJobPredicate;
57 *config.add_predicate() = screenIsOffPredicate;
58 *config.add_predicate() = isSyncingPredicate;
59 auto combinationPredicate = config.add_predicate();
60 combinationPredicate->set_id(StringToId("CombinationPredicate"));
61 combinationPredicate->mutable_combination()->set_operation(LogicalOperation::AND);
62 addPredicateToPredicateCombination(screenIsOffPredicate, combinationPredicate);
63 addPredicateToPredicateCombination(isSyncingPredicate, combinationPredicate);
64
65 auto metric = config.add_duration_metric();
66 metric->set_bucket(FIVE_MINUTES);
67 metric->set_id(StringToId("scheduledJob"));
68 metric->set_what(scheduledJobPredicate.id());
69 metric->set_condition(combinationPredicate->id());
70 metric->set_aggregation_type(aggregationType);
71 auto dimensionWhat = metric->mutable_dimensions_in_what();
72 dimensionWhat->set_field(util::SCHEDULED_JOB_STATE_CHANGED);
73 dimensionWhat->add_child()->set_field(2); // job name field.
74 *metric->mutable_dimensions_in_condition() =
75 CreateAttributionUidAndTagDimensions(util::SYNC_STATE_CHANGED, {Position::FIRST});
76 return config;
77 }
78
CreateDurationMetricConfig_Link_AND_CombinationCondition(DurationMetric::AggregationType aggregationType,bool addExtraDimensionInCondition)79 static StatsdConfig CreateDurationMetricConfig_Link_AND_CombinationCondition(
80 DurationMetric::AggregationType aggregationType, bool addExtraDimensionInCondition) {
81 StatsdConfig config;
82 *config.add_atom_matcher() = CreateStartScheduledJobAtomMatcher();
83 *config.add_atom_matcher() = CreateFinishScheduledJobAtomMatcher();
84 *config.add_atom_matcher() = CreateSyncStartAtomMatcher();
85 *config.add_atom_matcher() = CreateSyncEndAtomMatcher();
86 *config.add_atom_matcher() = CreateScreenTurnedOnAtomMatcher();
87 *config.add_atom_matcher() = CreateScreenTurnedOffAtomMatcher();
88
89 auto scheduledJobPredicate = CreateScheduledJobPredicate();
90 auto dimensions = scheduledJobPredicate.mutable_simple_predicate()->mutable_dimensions();
91 *dimensions =
92 CreateAttributionUidDimensions(util::SCHEDULED_JOB_STATE_CHANGED, {Position::FIRST});
93 dimensions->add_child()->set_field(2); // job name field.
94
95 auto isSyncingPredicate = CreateIsSyncingPredicate();
96 auto syncDimension = isSyncingPredicate.mutable_simple_predicate()->mutable_dimensions();
97 *syncDimension = CreateAttributionUidDimensions(util::SYNC_STATE_CHANGED, {Position::FIRST});
98 if (addExtraDimensionInCondition) {
99 syncDimension->add_child()->set_field(2 /* name field*/);
100 }
101
102 auto screenIsOffPredicate = CreateScreenIsOffPredicate();
103
104 *config.add_predicate() = scheduledJobPredicate;
105 *config.add_predicate() = screenIsOffPredicate;
106 *config.add_predicate() = isSyncingPredicate;
107 auto combinationPredicate = config.add_predicate();
108 combinationPredicate->set_id(StringToId("CombinationPredicate"));
109 combinationPredicate->mutable_combination()->set_operation(LogicalOperation::AND);
110 addPredicateToPredicateCombination(screenIsOffPredicate, combinationPredicate);
111 addPredicateToPredicateCombination(isSyncingPredicate, combinationPredicate);
112
113 auto metric = config.add_duration_metric();
114 metric->set_bucket(FIVE_MINUTES);
115 metric->set_id(StringToId("scheduledJob"));
116 metric->set_what(scheduledJobPredicate.id());
117 metric->set_condition(combinationPredicate->id());
118 metric->set_aggregation_type(aggregationType);
119 *metric->mutable_dimensions_in_what() =
120 CreateAttributionUidDimensions(util::SCHEDULED_JOB_STATE_CHANGED, {Position::FIRST});
121
122 auto links = metric->add_links();
123 links->set_condition(isSyncingPredicate.id());
124 *links->mutable_fields_in_what() =
125 CreateAttributionUidDimensions(util::SCHEDULED_JOB_STATE_CHANGED, {Position::FIRST});
126 *links->mutable_fields_in_condition() =
127 CreateAttributionUidDimensions(util::SYNC_STATE_CHANGED, {Position::FIRST});
128 return config;
129 }
130
BM_DurationMetricNoLink(benchmark::State & state)131 static void BM_DurationMetricNoLink(benchmark::State& state) {
132 ConfigKey cfgKey;
133 auto config = CreateDurationMetricConfig_NoLink_AND_CombinationCondition(
134 DurationMetric::SUM, false);
135 int64_t bucketStartTimeNs = 10000000000;
136 int64_t bucketSizeNs =
137 TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
138
139 std::vector<std::unique_ptr<LogEvent>> events;
140
141 events.push_back(CreateScreenStateChangedEvent(bucketStartTimeNs + 11,
142 android::view::DISPLAY_STATE_OFF));
143 events.push_back(
144 CreateScreenStateChangedEvent(bucketStartTimeNs + 40, android::view::DISPLAY_STATE_ON));
145
146 events.push_back(CreateScreenStateChangedEvent(bucketStartTimeNs + 102,
147 android::view::DISPLAY_STATE_OFF));
148 events.push_back(CreateScreenStateChangedEvent(bucketStartTimeNs + 450,
149 android::view::DISPLAY_STATE_ON));
150
151 events.push_back(CreateScreenStateChangedEvent(bucketStartTimeNs + 650,
152 android::view::DISPLAY_STATE_OFF));
153 events.push_back(CreateScreenStateChangedEvent(bucketStartTimeNs + bucketSizeNs + 100,
154 android::view::DISPLAY_STATE_ON));
155
156 events.push_back(CreateScreenStateChangedEvent(bucketStartTimeNs + bucketSizeNs + 640,
157 android::view::DISPLAY_STATE_OFF));
158 events.push_back(CreateScreenStateChangedEvent(bucketStartTimeNs + bucketSizeNs + 650,
159 android::view::DISPLAY_STATE_ON));
160
161 vector<int> attributionUids1 = {9999};
162 vector<string> attributionTags1 = {""};
163 events.push_back(CreateStartScheduledJobEvent(bucketStartTimeNs + 2, attributionUids1,
164 attributionTags1, "job0"));
165 events.push_back(CreateFinishScheduledJobEvent(bucketStartTimeNs + 101, attributionUids1,
166 attributionTags1, "job0"));
167
168 events.push_back(CreateStartScheduledJobEvent(bucketStartTimeNs + 201, attributionUids1,
169 attributionTags1, "job2"));
170 events.push_back(CreateFinishScheduledJobEvent(bucketStartTimeNs + 500, attributionUids1,
171 attributionTags1, "job2"));
172
173 vector<int> attributionUids2 = {8888};
174 events.push_back(CreateStartScheduledJobEvent(bucketStartTimeNs + 600, attributionUids2,
175 attributionTags1, "job2"));
176 events.push_back(CreateFinishScheduledJobEvent(bucketStartTimeNs + bucketSizeNs + 850,
177 attributionUids2, attributionTags1, "job2"));
178
179 events.push_back(CreateStartScheduledJobEvent(bucketStartTimeNs + bucketSizeNs + 600,
180 attributionUids2, attributionTags1, "job1"));
181 events.push_back(CreateFinishScheduledJobEvent(bucketStartTimeNs + bucketSizeNs + 900,
182 attributionUids2, attributionTags1, "job1"));
183
184 vector<int> attributionUids3 = {111, 222, 222};
185 vector<string> attributionTags3 = {"App1", "GMSCoreModule1", "GMSCoreModule2"};
186 events.push_back(CreateSyncStartEvent(bucketStartTimeNs + 10, attributionUids3,
187 attributionTags3, "ReadEmail"));
188 events.push_back(CreateSyncEndEvent(bucketStartTimeNs + 50, attributionUids3, attributionTags3,
189 "ReadEmail"));
190
191 events.push_back(CreateSyncStartEvent(bucketStartTimeNs + 200, attributionUids3,
192 attributionTags3, "ReadEmail"));
193 events.push_back(CreateSyncEndEvent(bucketStartTimeNs + bucketSizeNs + 300, attributionUids3,
194 attributionTags3, "ReadEmail"));
195
196 events.push_back(CreateSyncStartEvent(bucketStartTimeNs + 400, attributionUids3,
197 attributionTags3, "ReadDoc"));
198 events.push_back(CreateSyncEndEvent(bucketStartTimeNs + bucketSizeNs - 1, attributionUids3,
199 attributionTags3, "ReadDoc"));
200
201 vector<int> attributionUids4 = {333, 222, 555};
202 vector<string> attributionTags4 = {"App2", "GMSCoreModule1", "GMSCoreModule2"};
203 events.push_back(CreateSyncStartEvent(bucketStartTimeNs + 401, attributionUids4,
204 attributionTags4, "ReadEmail"));
205 events.push_back(CreateSyncEndEvent(bucketStartTimeNs + bucketSizeNs + 700, attributionUids4,
206 attributionTags4, "ReadEmail"));
207 sortLogEventsByTimestamp(&events);
208
209 while (state.KeepRunning()) {
210 auto processor =
211 CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
212 for (const auto& event : events) {
213 processor->OnLogEvent(event.get());
214 }
215 }
216 }
217
218 BENCHMARK(BM_DurationMetricNoLink);
219
220
BM_DurationMetricLink(benchmark::State & state)221 static void BM_DurationMetricLink(benchmark::State& state) {
222 ConfigKey cfgKey;
223 auto config = CreateDurationMetricConfig_Link_AND_CombinationCondition(
224 DurationMetric::SUM, false);
225 int64_t bucketStartTimeNs = 10000000000;
226 int64_t bucketSizeNs =
227 TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
228
229 std::vector<std::unique_ptr<LogEvent>> events;
230
231 events.push_back(CreateScreenStateChangedEvent(bucketStartTimeNs + 55,
232 android::view::DISPLAY_STATE_OFF));
233 events.push_back(CreateScreenStateChangedEvent(bucketStartTimeNs + 120,
234 android::view::DISPLAY_STATE_ON));
235 events.push_back(CreateScreenStateChangedEvent(bucketStartTimeNs + 121,
236 android::view::DISPLAY_STATE_OFF));
237 events.push_back(CreateScreenStateChangedEvent(bucketStartTimeNs + 450,
238 android::view::DISPLAY_STATE_ON));
239
240 events.push_back(CreateScreenStateChangedEvent(bucketStartTimeNs + 501,
241 android::view::DISPLAY_STATE_OFF));
242 events.push_back(CreateScreenStateChangedEvent(bucketStartTimeNs + bucketSizeNs + 100,
243 android::view::DISPLAY_STATE_ON));
244
245 vector<int> attributionUids1 = {111};
246 vector<string> attributionTags1 = {"App1"};
247 events.push_back(CreateStartScheduledJobEvent(bucketStartTimeNs + 1, attributionUids1,
248 attributionTags1, "job1"));
249 events.push_back(CreateFinishScheduledJobEvent(bucketStartTimeNs + 101, attributionUids1,
250 attributionTags1, "job1"));
251
252 vector<int> attributionUids2 = {333};
253 vector<string> attributionTags2 = {"App2"};
254 events.push_back(CreateStartScheduledJobEvent(bucketStartTimeNs + 201, attributionUids2,
255 attributionTags2, "job2"));
256 events.push_back(CreateFinishScheduledJobEvent(bucketStartTimeNs + 500, attributionUids2,
257 attributionTags2, "job2"));
258 events.push_back(CreateStartScheduledJobEvent(bucketStartTimeNs + 600, attributionUids2,
259 attributionTags2, "job2"));
260 events.push_back(CreateFinishScheduledJobEvent(bucketStartTimeNs + bucketSizeNs + 850,
261 attributionUids2, attributionTags2, "job2"));
262
263 vector<int> attributionUids3 = {444};
264 vector<string> attributionTags3 = {"App3"};
265 events.push_back(CreateStartScheduledJobEvent(bucketStartTimeNs + bucketSizeNs - 2,
266 attributionUids3, attributionTags3, "job3"));
267 events.push_back(CreateFinishScheduledJobEvent(bucketStartTimeNs + bucketSizeNs + 900,
268 attributionUids3, attributionTags3, "job3"));
269
270 vector<int> attributionUids4 = {111, 222, 222};
271 vector<string> attributionTags4 = {"App1", "GMSCoreModule1", "GMSCoreModule2"};
272 events.push_back(CreateSyncStartEvent(bucketStartTimeNs + 50, attributionUids4,
273 attributionTags4, "ReadEmail"));
274 events.push_back(CreateSyncEndEvent(bucketStartTimeNs + 110, attributionUids4, attributionTags4,
275 "ReadEmail"));
276
277 vector<int> attributionUids5 = {333, 222, 555};
278 vector<string> attributionTags5 = {"App2", "GMSCoreModule1", "GMSCoreModule2"};
279 events.push_back(CreateSyncStartEvent(bucketStartTimeNs + 300, attributionUids5,
280 attributionTags5, "ReadEmail"));
281 events.push_back(CreateSyncEndEvent(bucketStartTimeNs + bucketSizeNs + 700, attributionUids5,
282 attributionTags5, "ReadEmail"));
283 events.push_back(CreateSyncStartEvent(bucketStartTimeNs + 400, attributionUids5,
284 attributionTags5, "ReadDoc"));
285 events.push_back(CreateSyncEndEvent(bucketStartTimeNs + bucketSizeNs - 1, attributionUids5,
286 attributionTags5, "ReadDoc"));
287
288 vector<int> attributionUids6 = {444, 222, 555};
289 vector<string> attributionTags6 = {"App3", "GMSCoreModule1", "GMSCoreModule2"};
290 events.push_back(CreateSyncStartEvent(bucketStartTimeNs + 550, attributionUids6,
291 attributionTags6, "ReadDoc"));
292 events.push_back(CreateSyncEndEvent(bucketStartTimeNs + 800, attributionUids6, attributionTags6,
293 "ReadDoc"));
294 events.push_back(CreateSyncStartEvent(bucketStartTimeNs + bucketSizeNs - 1, attributionUids6,
295 attributionTags6, "ReadDoc"));
296 events.push_back(CreateSyncEndEvent(bucketStartTimeNs + bucketSizeNs + 700, attributionUids6,
297 attributionTags6, "ReadDoc"));
298 sortLogEventsByTimestamp(&events);
299
300 while (state.KeepRunning()) {
301 auto processor =
302 CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
303 for (const auto& event : events) {
304 processor->OnLogEvent(event.get());
305 }
306 }
307 }
308
309 BENCHMARK(BM_DurationMetricLink);
310
311 } // namespace statsd
312 } // namespace os
313 } // namespace android
314