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 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 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 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 141 std::vector<AttributionNodeInternal> attributions1 = { 142 CreateAttribution(111, "App1"), CreateAttribution(222, "GMSCoreModule1"), 143 CreateAttribution(222, "GMSCoreModule2")}; 144 145 std::vector<AttributionNodeInternal> attributions2 = { 146 CreateAttribution(333, "App2"), CreateAttribution(222, "GMSCoreModule1"), 147 CreateAttribution(555, "GMSCoreModule2")}; 148 149 std::vector<std::unique_ptr<LogEvent>> events; 150 151 events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF, 152 bucketStartTimeNs + 11)); 153 events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON, 154 bucketStartTimeNs + 40)); 155 156 events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF, 157 bucketStartTimeNs + 102)); 158 events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON, 159 bucketStartTimeNs + 450)); 160 161 events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF, 162 bucketStartTimeNs + 650)); 163 events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON, 164 bucketStartTimeNs + bucketSizeNs + 100)); 165 166 events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF, 167 bucketStartTimeNs + bucketSizeNs + 640)); 168 events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON, 169 bucketStartTimeNs + bucketSizeNs + 650)); 170 171 events.push_back(CreateStartScheduledJobEvent( 172 {CreateAttribution(9999, "")}, "job0", bucketStartTimeNs + 2)); 173 events.push_back(CreateFinishScheduledJobEvent( 174 {CreateAttribution(9999, "")}, "job0",bucketStartTimeNs + 101)); 175 176 events.push_back(CreateStartScheduledJobEvent( 177 {CreateAttribution(9999, "")}, "job2", bucketStartTimeNs + 201)); 178 events.push_back(CreateFinishScheduledJobEvent( 179 {CreateAttribution(9999, "")}, "job2",bucketStartTimeNs + 500)); 180 181 events.push_back(CreateStartScheduledJobEvent( 182 {CreateAttribution(8888, "")}, "job2", bucketStartTimeNs + 600)); 183 events.push_back(CreateFinishScheduledJobEvent( 184 {CreateAttribution(8888, "")}, "job2",bucketStartTimeNs + bucketSizeNs + 850)); 185 186 events.push_back(CreateStartScheduledJobEvent( 187 {CreateAttribution(8888, "")}, "job1", bucketStartTimeNs + bucketSizeNs + 600)); 188 events.push_back(CreateFinishScheduledJobEvent( 189 {CreateAttribution(8888, "")}, "job1", bucketStartTimeNs + bucketSizeNs + 900)); 190 191 events.push_back(CreateSyncStartEvent(attributions1, "ReadEmail", 192 bucketStartTimeNs + 10)); 193 events.push_back(CreateSyncEndEvent(attributions1, "ReadEmail", 194 bucketStartTimeNs + 50)); 195 196 events.push_back(CreateSyncStartEvent(attributions1, "ReadEmail", 197 bucketStartTimeNs + 200)); 198 events.push_back(CreateSyncEndEvent(attributions1, "ReadEmail", 199 bucketStartTimeNs + bucketSizeNs + 300)); 200 201 events.push_back(CreateSyncStartEvent(attributions1, "ReadDoc", 202 bucketStartTimeNs + 400)); 203 events.push_back(CreateSyncEndEvent(attributions1, "ReadDoc", 204 bucketStartTimeNs + bucketSizeNs - 1)); 205 206 events.push_back(CreateSyncStartEvent(attributions2, "ReadEmail", 207 bucketStartTimeNs + 401)); 208 events.push_back(CreateSyncEndEvent(attributions2, "ReadEmail", 209 bucketStartTimeNs + bucketSizeNs + 700)); 210 211 sortLogEventsByTimestamp(&events); 212 213 while (state.KeepRunning()) { 214 auto processor = CreateStatsLogProcessor( 215 bucketStartTimeNs / NS_PER_SEC, config, cfgKey); 216 for (const auto& event : events) { 217 processor->OnLogEvent(event.get()); 218 } 219 } 220 } 221 222 BENCHMARK(BM_DurationMetricNoLink); 223 224 225 static void BM_DurationMetricLink(benchmark::State& state) { 226 ConfigKey cfgKey; 227 auto config = CreateDurationMetricConfig_Link_AND_CombinationCondition( 228 DurationMetric::SUM, false); 229 int64_t bucketStartTimeNs = 10000000000; 230 int64_t bucketSizeNs = 231 TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL; 232 233 std::vector<AttributionNodeInternal> attributions1 = { 234 CreateAttribution(111, "App1"), CreateAttribution(222, "GMSCoreModule1"), 235 CreateAttribution(222, "GMSCoreModule2")}; 236 237 std::vector<AttributionNodeInternal> attributions2 = { 238 CreateAttribution(333, "App2"), CreateAttribution(222, "GMSCoreModule1"), 239 CreateAttribution(555, "GMSCoreModule2")}; 240 241 std::vector<AttributionNodeInternal> attributions3 = { 242 CreateAttribution(444, "App3"), CreateAttribution(222, "GMSCoreModule1"), 243 CreateAttribution(555, "GMSCoreModule2")}; 244 245 std::vector<std::unique_ptr<LogEvent>> events; 246 247 events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF, 248 bucketStartTimeNs + 55)); 249 events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON, 250 bucketStartTimeNs + 120)); 251 events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF, 252 bucketStartTimeNs + 121)); 253 events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON, 254 bucketStartTimeNs + 450)); 255 256 events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF, 257 bucketStartTimeNs + 501)); 258 events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON, 259 bucketStartTimeNs + bucketSizeNs + 100)); 260 261 events.push_back(CreateStartScheduledJobEvent( 262 {CreateAttribution(111, "App1")}, "job1", bucketStartTimeNs + 1)); 263 events.push_back(CreateFinishScheduledJobEvent( 264 {CreateAttribution(111, "App1")}, "job1",bucketStartTimeNs + 101)); 265 266 events.push_back(CreateStartScheduledJobEvent( 267 {CreateAttribution(333, "App2")}, "job2", bucketStartTimeNs + 201)); 268 events.push_back(CreateFinishScheduledJobEvent( 269 {CreateAttribution(333, "App2")}, "job2",bucketStartTimeNs + 500)); 270 events.push_back(CreateStartScheduledJobEvent( 271 {CreateAttribution(333, "App2")}, "job2", bucketStartTimeNs + 600)); 272 events.push_back(CreateFinishScheduledJobEvent( 273 {CreateAttribution(333, "App2")}, "job2", 274 bucketStartTimeNs + bucketSizeNs + 850)); 275 276 events.push_back( 277 CreateStartScheduledJobEvent({CreateAttribution(444, "App3")}, "job3", 278 bucketStartTimeNs + bucketSizeNs - 2)); 279 events.push_back( 280 CreateFinishScheduledJobEvent({CreateAttribution(444, "App3")}, "job3", 281 bucketStartTimeNs + bucketSizeNs + 900)); 282 283 events.push_back(CreateSyncStartEvent(attributions1, "ReadEmail", 284 bucketStartTimeNs + 50)); 285 events.push_back(CreateSyncEndEvent(attributions1, "ReadEmail", 286 bucketStartTimeNs + 110)); 287 288 events.push_back(CreateSyncStartEvent(attributions2, "ReadEmail", 289 bucketStartTimeNs + 300)); 290 events.push_back(CreateSyncEndEvent(attributions2, "ReadEmail", 291 bucketStartTimeNs + bucketSizeNs + 700)); 292 events.push_back(CreateSyncStartEvent(attributions2, "ReadDoc", 293 bucketStartTimeNs + 400)); 294 events.push_back(CreateSyncEndEvent(attributions2, "ReadDoc", 295 bucketStartTimeNs + bucketSizeNs - 1)); 296 297 events.push_back(CreateSyncStartEvent(attributions3, "ReadDoc", 298 bucketStartTimeNs + 550)); 299 events.push_back(CreateSyncEndEvent(attributions3, "ReadDoc", 300 bucketStartTimeNs + 800)); 301 events.push_back(CreateSyncStartEvent(attributions3, "ReadDoc", 302 bucketStartTimeNs + bucketSizeNs - 1)); 303 events.push_back(CreateSyncEndEvent(attributions3, "ReadDoc", 304 bucketStartTimeNs + bucketSizeNs + 700)); 305 sortLogEventsByTimestamp(&events); 306 307 while (state.KeepRunning()) { 308 auto processor = CreateStatsLogProcessor( 309 bucketStartTimeNs / NS_PER_SEC, config, cfgKey); 310 for (const auto& event : events) { 311 processor->OnLogEvent(event.get()); 312 } 313 } 314 } 315 316 BENCHMARK(BM_DurationMetricLink); 317 318 } // namespace statsd 319 } // namespace os 320 } // namespace android 321