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