| /* |
| * Copyright (C) 2018 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| #include <vector> |
| #include "benchmark/benchmark.h" |
| #include "FieldValue.h" |
| #include "HashableDimensionKey.h" |
| #include "logd/LogEvent.h" |
| #include "stats_log_util.h" |
| #include "metric_util.h" |
| |
| namespace android { |
| namespace os { |
| namespace statsd { |
| |
| using std::vector; |
| |
| static StatsdConfig CreateDurationMetricConfig_NoLink_AND_CombinationCondition( |
| DurationMetric::AggregationType aggregationType, bool addExtraDimensionInCondition) { |
| StatsdConfig config; |
| *config.add_atom_matcher() = CreateStartScheduledJobAtomMatcher(); |
| *config.add_atom_matcher() = CreateFinishScheduledJobAtomMatcher(); |
| *config.add_atom_matcher() = CreateSyncStartAtomMatcher(); |
| *config.add_atom_matcher() = CreateSyncEndAtomMatcher(); |
| *config.add_atom_matcher() = CreateScreenTurnedOnAtomMatcher(); |
| *config.add_atom_matcher() = CreateScreenTurnedOffAtomMatcher(); |
| |
| auto scheduledJobPredicate = CreateScheduledJobPredicate(); |
| auto dimensions = scheduledJobPredicate.mutable_simple_predicate()->mutable_dimensions(); |
| dimensions->set_field(android::util::SCHEDULED_JOB_STATE_CHANGED); |
| dimensions->add_child()->set_field(2); // job name field. |
| |
| auto screenIsOffPredicate = CreateScreenIsOffPredicate(); |
| |
| auto isSyncingPredicate = CreateIsSyncingPredicate(); |
| auto syncDimension = isSyncingPredicate.mutable_simple_predicate()->mutable_dimensions(); |
| *syncDimension = CreateAttributionUidAndTagDimensions(android::util::SYNC_STATE_CHANGED, |
| {Position::FIRST}); |
| if (addExtraDimensionInCondition) { |
| syncDimension->add_child()->set_field(2 /* name field*/); |
| } |
| |
| *config.add_predicate() = scheduledJobPredicate; |
| *config.add_predicate() = screenIsOffPredicate; |
| *config.add_predicate() = isSyncingPredicate; |
| auto combinationPredicate = config.add_predicate(); |
| combinationPredicate->set_id(StringToId("CombinationPredicate")); |
| combinationPredicate->mutable_combination()->set_operation(LogicalOperation::AND); |
| addPredicateToPredicateCombination(screenIsOffPredicate, combinationPredicate); |
| addPredicateToPredicateCombination(isSyncingPredicate, combinationPredicate); |
| |
| auto metric = config.add_duration_metric(); |
| metric->set_bucket(FIVE_MINUTES); |
| metric->set_id(StringToId("scheduledJob")); |
| metric->set_what(scheduledJobPredicate.id()); |
| metric->set_condition(combinationPredicate->id()); |
| metric->set_aggregation_type(aggregationType); |
| auto dimensionWhat = metric->mutable_dimensions_in_what(); |
| dimensionWhat->set_field(android::util::SCHEDULED_JOB_STATE_CHANGED); |
| dimensionWhat->add_child()->set_field(2); // job name field. |
| *metric->mutable_dimensions_in_condition() = CreateAttributionUidAndTagDimensions( |
| android::util::SYNC_STATE_CHANGED, {Position::FIRST}); |
| return config; |
| } |
| |
| static StatsdConfig CreateDurationMetricConfig_Link_AND_CombinationCondition( |
| DurationMetric::AggregationType aggregationType, bool addExtraDimensionInCondition) { |
| StatsdConfig config; |
| *config.add_atom_matcher() = CreateStartScheduledJobAtomMatcher(); |
| *config.add_atom_matcher() = CreateFinishScheduledJobAtomMatcher(); |
| *config.add_atom_matcher() = CreateSyncStartAtomMatcher(); |
| *config.add_atom_matcher() = CreateSyncEndAtomMatcher(); |
| *config.add_atom_matcher() = CreateScreenTurnedOnAtomMatcher(); |
| *config.add_atom_matcher() = CreateScreenTurnedOffAtomMatcher(); |
| |
| auto scheduledJobPredicate = CreateScheduledJobPredicate(); |
| auto dimensions = scheduledJobPredicate.mutable_simple_predicate()->mutable_dimensions(); |
| *dimensions = CreateAttributionUidDimensions( |
| android::util::SCHEDULED_JOB_STATE_CHANGED, {Position::FIRST}); |
| dimensions->add_child()->set_field(2); // job name field. |
| |
| auto isSyncingPredicate = CreateIsSyncingPredicate(); |
| auto syncDimension = isSyncingPredicate.mutable_simple_predicate()->mutable_dimensions(); |
| *syncDimension = CreateAttributionUidDimensions( |
| android::util::SYNC_STATE_CHANGED, {Position::FIRST}); |
| if (addExtraDimensionInCondition) { |
| syncDimension->add_child()->set_field(2 /* name field*/); |
| } |
| |
| auto screenIsOffPredicate = CreateScreenIsOffPredicate(); |
| |
| *config.add_predicate() = scheduledJobPredicate; |
| *config.add_predicate() = screenIsOffPredicate; |
| *config.add_predicate() = isSyncingPredicate; |
| auto combinationPredicate = config.add_predicate(); |
| combinationPredicate->set_id(StringToId("CombinationPredicate")); |
| combinationPredicate->mutable_combination()->set_operation(LogicalOperation::AND); |
| addPredicateToPredicateCombination(screenIsOffPredicate, combinationPredicate); |
| addPredicateToPredicateCombination(isSyncingPredicate, combinationPredicate); |
| |
| auto metric = config.add_duration_metric(); |
| metric->set_bucket(FIVE_MINUTES); |
| metric->set_id(StringToId("scheduledJob")); |
| metric->set_what(scheduledJobPredicate.id()); |
| metric->set_condition(combinationPredicate->id()); |
| metric->set_aggregation_type(aggregationType); |
| *metric->mutable_dimensions_in_what() = CreateAttributionUidDimensions( |
| android::util::SCHEDULED_JOB_STATE_CHANGED, {Position::FIRST}); |
| |
| auto links = metric->add_links(); |
| links->set_condition(isSyncingPredicate.id()); |
| *links->mutable_fields_in_what() = |
| CreateAttributionUidDimensions( |
| android::util::SCHEDULED_JOB_STATE_CHANGED, {Position::FIRST}); |
| *links->mutable_fields_in_condition() = |
| CreateAttributionUidDimensions(android::util::SYNC_STATE_CHANGED, {Position::FIRST}); |
| return config; |
| } |
| |
| static void BM_DurationMetricNoLink(benchmark::State& state) { |
| ConfigKey cfgKey; |
| auto config = CreateDurationMetricConfig_NoLink_AND_CombinationCondition( |
| DurationMetric::SUM, false); |
| int64_t bucketStartTimeNs = 10000000000; |
| int64_t bucketSizeNs = |
| TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL; |
| |
| |
| std::vector<AttributionNodeInternal> attributions1 = { |
| CreateAttribution(111, "App1"), CreateAttribution(222, "GMSCoreModule1"), |
| CreateAttribution(222, "GMSCoreModule2")}; |
| |
| std::vector<AttributionNodeInternal> attributions2 = { |
| CreateAttribution(333, "App2"), CreateAttribution(222, "GMSCoreModule1"), |
| CreateAttribution(555, "GMSCoreModule2")}; |
| |
| std::vector<std::unique_ptr<LogEvent>> events; |
| |
| events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF, |
| bucketStartTimeNs + 11)); |
| events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON, |
| bucketStartTimeNs + 40)); |
| |
| events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF, |
| bucketStartTimeNs + 102)); |
| events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON, |
| bucketStartTimeNs + 450)); |
| |
| events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF, |
| bucketStartTimeNs + 650)); |
| events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON, |
| bucketStartTimeNs + bucketSizeNs + 100)); |
| |
| events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF, |
| bucketStartTimeNs + bucketSizeNs + 640)); |
| events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON, |
| bucketStartTimeNs + bucketSizeNs + 650)); |
| |
| events.push_back(CreateStartScheduledJobEvent( |
| {CreateAttribution(9999, "")}, "job0", bucketStartTimeNs + 2)); |
| events.push_back(CreateFinishScheduledJobEvent( |
| {CreateAttribution(9999, "")}, "job0",bucketStartTimeNs + 101)); |
| |
| events.push_back(CreateStartScheduledJobEvent( |
| {CreateAttribution(9999, "")}, "job2", bucketStartTimeNs + 201)); |
| events.push_back(CreateFinishScheduledJobEvent( |
| {CreateAttribution(9999, "")}, "job2",bucketStartTimeNs + 500)); |
| |
| events.push_back(CreateStartScheduledJobEvent( |
| {CreateAttribution(8888, "")}, "job2", bucketStartTimeNs + 600)); |
| events.push_back(CreateFinishScheduledJobEvent( |
| {CreateAttribution(8888, "")}, "job2",bucketStartTimeNs + bucketSizeNs + 850)); |
| |
| events.push_back(CreateStartScheduledJobEvent( |
| {CreateAttribution(8888, "")}, "job1", bucketStartTimeNs + bucketSizeNs + 600)); |
| events.push_back(CreateFinishScheduledJobEvent( |
| {CreateAttribution(8888, "")}, "job1", bucketStartTimeNs + bucketSizeNs + 900)); |
| |
| events.push_back(CreateSyncStartEvent(attributions1, "ReadEmail", |
| bucketStartTimeNs + 10)); |
| events.push_back(CreateSyncEndEvent(attributions1, "ReadEmail", |
| bucketStartTimeNs + 50)); |
| |
| events.push_back(CreateSyncStartEvent(attributions1, "ReadEmail", |
| bucketStartTimeNs + 200)); |
| events.push_back(CreateSyncEndEvent(attributions1, "ReadEmail", |
| bucketStartTimeNs + bucketSizeNs + 300)); |
| |
| events.push_back(CreateSyncStartEvent(attributions1, "ReadDoc", |
| bucketStartTimeNs + 400)); |
| events.push_back(CreateSyncEndEvent(attributions1, "ReadDoc", |
| bucketStartTimeNs + bucketSizeNs - 1)); |
| |
| events.push_back(CreateSyncStartEvent(attributions2, "ReadEmail", |
| bucketStartTimeNs + 401)); |
| events.push_back(CreateSyncEndEvent(attributions2, "ReadEmail", |
| bucketStartTimeNs + bucketSizeNs + 700)); |
| |
| sortLogEventsByTimestamp(&events); |
| |
| while (state.KeepRunning()) { |
| auto processor = CreateStatsLogProcessor( |
| bucketStartTimeNs / NS_PER_SEC, config, cfgKey); |
| for (const auto& event : events) { |
| processor->OnLogEvent(event.get()); |
| } |
| } |
| } |
| |
| BENCHMARK(BM_DurationMetricNoLink); |
| |
| |
| static void BM_DurationMetricLink(benchmark::State& state) { |
| ConfigKey cfgKey; |
| auto config = CreateDurationMetricConfig_Link_AND_CombinationCondition( |
| DurationMetric::SUM, false); |
| int64_t bucketStartTimeNs = 10000000000; |
| int64_t bucketSizeNs = |
| TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL; |
| |
| std::vector<AttributionNodeInternal> attributions1 = { |
| CreateAttribution(111, "App1"), CreateAttribution(222, "GMSCoreModule1"), |
| CreateAttribution(222, "GMSCoreModule2")}; |
| |
| std::vector<AttributionNodeInternal> attributions2 = { |
| CreateAttribution(333, "App2"), CreateAttribution(222, "GMSCoreModule1"), |
| CreateAttribution(555, "GMSCoreModule2")}; |
| |
| std::vector<AttributionNodeInternal> attributions3 = { |
| CreateAttribution(444, "App3"), CreateAttribution(222, "GMSCoreModule1"), |
| CreateAttribution(555, "GMSCoreModule2")}; |
| |
| std::vector<std::unique_ptr<LogEvent>> events; |
| |
| events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF, |
| bucketStartTimeNs + 55)); |
| events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON, |
| bucketStartTimeNs + 120)); |
| events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF, |
| bucketStartTimeNs + 121)); |
| events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON, |
| bucketStartTimeNs + 450)); |
| |
| events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF, |
| bucketStartTimeNs + 501)); |
| events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON, |
| bucketStartTimeNs + bucketSizeNs + 100)); |
| |
| events.push_back(CreateStartScheduledJobEvent( |
| {CreateAttribution(111, "App1")}, "job1", bucketStartTimeNs + 1)); |
| events.push_back(CreateFinishScheduledJobEvent( |
| {CreateAttribution(111, "App1")}, "job1",bucketStartTimeNs + 101)); |
| |
| events.push_back(CreateStartScheduledJobEvent( |
| {CreateAttribution(333, "App2")}, "job2", bucketStartTimeNs + 201)); |
| events.push_back(CreateFinishScheduledJobEvent( |
| {CreateAttribution(333, "App2")}, "job2",bucketStartTimeNs + 500)); |
| events.push_back(CreateStartScheduledJobEvent( |
| {CreateAttribution(333, "App2")}, "job2", bucketStartTimeNs + 600)); |
| events.push_back(CreateFinishScheduledJobEvent( |
| {CreateAttribution(333, "App2")}, "job2", |
| bucketStartTimeNs + bucketSizeNs + 850)); |
| |
| events.push_back( |
| CreateStartScheduledJobEvent({CreateAttribution(444, "App3")}, "job3", |
| bucketStartTimeNs + bucketSizeNs - 2)); |
| events.push_back( |
| CreateFinishScheduledJobEvent({CreateAttribution(444, "App3")}, "job3", |
| bucketStartTimeNs + bucketSizeNs + 900)); |
| |
| events.push_back(CreateSyncStartEvent(attributions1, "ReadEmail", |
| bucketStartTimeNs + 50)); |
| events.push_back(CreateSyncEndEvent(attributions1, "ReadEmail", |
| bucketStartTimeNs + 110)); |
| |
| events.push_back(CreateSyncStartEvent(attributions2, "ReadEmail", |
| bucketStartTimeNs + 300)); |
| events.push_back(CreateSyncEndEvent(attributions2, "ReadEmail", |
| bucketStartTimeNs + bucketSizeNs + 700)); |
| events.push_back(CreateSyncStartEvent(attributions2, "ReadDoc", |
| bucketStartTimeNs + 400)); |
| events.push_back(CreateSyncEndEvent(attributions2, "ReadDoc", |
| bucketStartTimeNs + bucketSizeNs - 1)); |
| |
| events.push_back(CreateSyncStartEvent(attributions3, "ReadDoc", |
| bucketStartTimeNs + 550)); |
| events.push_back(CreateSyncEndEvent(attributions3, "ReadDoc", |
| bucketStartTimeNs + 800)); |
| events.push_back(CreateSyncStartEvent(attributions3, "ReadDoc", |
| bucketStartTimeNs + bucketSizeNs - 1)); |
| events.push_back(CreateSyncEndEvent(attributions3, "ReadDoc", |
| bucketStartTimeNs + bucketSizeNs + 700)); |
| sortLogEventsByTimestamp(&events); |
| |
| while (state.KeepRunning()) { |
| auto processor = CreateStatsLogProcessor( |
| bucketStartTimeNs / NS_PER_SEC, config, cfgKey); |
| for (const auto& event : events) { |
| processor->OnLogEvent(event.get()); |
| } |
| } |
| } |
| |
| BENCHMARK(BM_DurationMetricLink); |
| |
| } // namespace statsd |
| } // namespace os |
| } // namespace android |