1 /*
2 * Copyright (C) 2024 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
17 #include <memory>
18
19 #include "benchmark/benchmark.h"
20 #include "src/statsd_config.pb.h"
21 #include "tests/statsd_test_util.h"
22
23 using namespace std;
24
25 namespace android {
26 namespace os {
27 namespace statsd {
28 namespace {
29
30 const ConfigKey cfgKey(0, 12345);
31 const int numOfMetrics = 4;
32
createExpressEventReportedEvents()33 vector<shared_ptr<LogEvent>> createExpressEventReportedEvents() {
34 vector<shared_ptr<LogEvent>> events;
35 for (int i = 0; i < numOfMetrics; i++) {
36 events.push_back(CreateTwoValueLogEvent(/* atomId */ util::EXPRESS_EVENT_REPORTED,
37 /* eventTimeNs */ i,
38 /* metric_id */ i % numOfMetrics, /* value */ 1));
39 }
40 return events;
41 }
42
CreateExpressEventReportedAtomMatcher(const string & name,int64_t metricIdHash)43 AtomMatcher CreateExpressEventReportedAtomMatcher(const string& name, int64_t metricIdHash) {
44 AtomMatcher atom_matcher = CreateSimpleAtomMatcher(name, util::EXPRESS_EVENT_REPORTED);
45 auto simple_atom_matcher = atom_matcher.mutable_simple_atom_matcher();
46 auto field_value_matcher = simple_atom_matcher->add_field_value_matcher();
47 field_value_matcher->set_field(1); // metric id hash as int64
48 field_value_matcher->set_eq_int(metricIdHash);
49 return atom_matcher;
50 }
51
createTexConfig()52 StatsdConfig createTexConfig() {
53 StatsdConfig config;
54 *config.add_atom_matcher() = CreateExpressEventReportedAtomMatcher("texMatcher1", 0);
55 *config.add_atom_matcher() = CreateExpressEventReportedAtomMatcher("texMatcher2", 1);
56 *config.add_atom_matcher() = CreateExpressEventReportedAtomMatcher("texMatcher3", 2);
57 *config.add_atom_matcher() = CreateExpressEventReportedAtomMatcher("texMatcher4", 3);
58
59 *config.add_value_metric() =
60 createValueMetric("texValue1", config.atom_matcher(0), /* valueField */ 2,
61 /* condition */ nullopt, /* states */ {});
62 *config.add_value_metric() =
63 createValueMetric("texValue2", config.atom_matcher(1), /* valueField */ 2,
64 /* condition */ nullopt, /* states */ {});
65 *config.add_value_metric() =
66 createValueMetric("texValue3", config.atom_matcher(2), /* valueField */ 2,
67 /* condition */ nullopt, /* states */ {});
68 *config.add_value_metric() =
69 createValueMetric("texValue4", config.atom_matcher(3), /* valueField */ 2,
70 /* condition */ nullopt, /* states */ {});
71 return config;
72 }
73
createCountMetricConfig()74 StatsdConfig createCountMetricConfig() {
75 StatsdConfig config;
76 *config.add_atom_matcher() =
77 CreateSimpleAtomMatcher("someCounterMatcher", /*atomId*/ util::EXPRESS_EVENT_REPORTED);
78
79 CountMetric* countMetric = config.add_count_metric();
80 *countMetric = createCountMetric("CountMetricAsCounter", /* what */ config.atom_matcher(0).id(),
81 /* condition */ nullopt, /* states */ {});
82 countMetric->mutable_dimensions_in_what()->set_field(util::EXPRESS_EVENT_REPORTED);
83 countMetric->mutable_dimensions_in_what()->add_child()->set_field(1);
84 return config;
85 }
86
createValueMetricConfig()87 StatsdConfig createValueMetricConfig() {
88 StatsdConfig config;
89 *config.add_atom_matcher() =
90 CreateSimpleAtomMatcher("someValueMatcher", /*atomId*/ util::EXPRESS_EVENT_REPORTED);
91
92 ValueMetric* valueMetric = config.add_value_metric();
93 *valueMetric = createValueMetric("ValueMetricAsCounter", /* what */ config.atom_matcher(0),
94 /* valueField */ 2,
95 /* condition */ nullopt,
96 /* states */ {});
97 valueMetric->mutable_dimensions_in_what()->set_field(util::EXPRESS_EVENT_REPORTED);
98 valueMetric->mutable_dimensions_in_what()->add_child()->set_field(1);
99 return config;
100 }
101
testScenario(benchmark::State & state,sp<StatsLogProcessor> & processor)102 void testScenario(benchmark::State& state, sp<StatsLogProcessor>& processor) {
103 const int64_t elevenMinutesInNanos = NS_PER_SEC * 60 * 11;
104 vector<shared_ptr<LogEvent>> events = createExpressEventReportedEvents();
105 state.counters["MetricsSize"] = processor->GetMetricsSize(cfgKey);
106 int64_t eventIndex = 0;
107 for (auto _ : state) {
108 for (int i = 0; i < 1000; i++) {
109 auto event = events[eventIndex % numOfMetrics].get();
110 event->setElapsedTimestampNs(eventIndex * 10);
111 processor->OnLogEvent(event);
112 benchmark::DoNotOptimize(processor);
113 eventIndex++;
114 }
115 }
116 vector<uint8_t> buffer;
117 processor->onDumpReport(cfgKey, elevenMinutesInNanos, true, false, ADB_DUMP, FAST, &buffer);
118 state.counters["ReportBufferSize"] = buffer.size();
119 state.counters["MetricsSizeFinal"] = processor->GetMetricsSize(cfgKey);
120 }
121
BM_TexCounter(benchmark::State & state)122 void BM_TexCounter(benchmark::State& state) {
123 // idea is to have 1 standalone value metric with dimensions to mimic 4 tex metrics
124 // and compare performance - see BM_TexCounterAsValueMetric
125 StatsdConfig config = createTexConfig();
126 sp<StatsLogProcessor> processor = CreateStatsLogProcessor(1, 1, config, cfgKey);
127 testScenario(state, processor);
128 }
129 BENCHMARK(BM_TexCounter);
130
BM_TexCounterAsValueMetric(benchmark::State & state)131 void BM_TexCounterAsValueMetric(benchmark::State& state) {
132 // idea is to have 1 standalone value metric with dimensions to mimic 4 tex metrics
133 // and compare performance - see BM_TexCounter
134 StatsdConfig config = createValueMetricConfig();
135 sp<StatsLogProcessor> processor = CreateStatsLogProcessor(1, 1, config, cfgKey);
136 testScenario(state, processor);
137 }
138 BENCHMARK(BM_TexCounterAsValueMetric);
139
BM_TexCounterAsCountMetric(benchmark::State & state)140 void BM_TexCounterAsCountMetric(benchmark::State& state) {
141 // idea is to have 1 standalone count metric with dimensions to mimic 4 tex metrics
142 // and compare performance - see BM_TexCounter
143 StatsdConfig config = createCountMetricConfig();
144 sp<StatsLogProcessor> processor = CreateStatsLogProcessor(1, 1, config, cfgKey);
145 testScenario(state, processor);
146 }
147 BENCHMARK(BM_TexCounterAsCountMetric);
148
149 } // anonymous namespace
150 } // namespace statsd
151 } // namespace os
152 } // namespace android
153