1*77b80299SAndroid Build Coastguard Worker /*
2*77b80299SAndroid Build Coastguard Worker * Copyright (C) 2016 The Android Open Source Project
3*77b80299SAndroid Build Coastguard Worker *
4*77b80299SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*77b80299SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*77b80299SAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*77b80299SAndroid Build Coastguard Worker *
8*77b80299SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*77b80299SAndroid Build Coastguard Worker *
10*77b80299SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*77b80299SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*77b80299SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*77b80299SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*77b80299SAndroid Build Coastguard Worker * limitations under the License.
15*77b80299SAndroid Build Coastguard Worker */
16*77b80299SAndroid Build Coastguard Worker
17*77b80299SAndroid Build Coastguard Worker #include "PerfTest.h"
18*77b80299SAndroid Build Coastguard Worker #include <fstream>
19*77b80299SAndroid Build Coastguard Worker #include <iomanip>
20*77b80299SAndroid Build Coastguard Worker #include <iostream>
21*77b80299SAndroid Build Coastguard Worker #include <string>
22*77b80299SAndroid Build Coastguard Worker
23*77b80299SAndroid Build Coastguard Worker #ifdef ASSERT
24*77b80299SAndroid Build Coastguard Worker #undef ASSERT
25*77b80299SAndroid Build Coastguard Worker #endif
26*77b80299SAndroid Build Coastguard Worker #define ASSERT(cond) \
27*77b80299SAndroid Build Coastguard Worker do { \
28*77b80299SAndroid Build Coastguard Worker if (!(cond)) { \
29*77b80299SAndroid Build Coastguard Worker cerr << __func__ << ":" << __LINE__ << " condition:" << #cond << " failed\n" << endl; \
30*77b80299SAndroid Build Coastguard Worker exit(EXIT_FAILURE); \
31*77b80299SAndroid Build Coastguard Worker } \
32*77b80299SAndroid Build Coastguard Worker } while (0)
33*77b80299SAndroid Build Coastguard Worker
34*77b80299SAndroid Build Coastguard Worker // the ratio that the service is synced on the same cpu beyond
35*77b80299SAndroid Build Coastguard Worker // GOOD_SYNC_MIN is considered as good
36*77b80299SAndroid Build Coastguard Worker #define GOOD_SYNC_MIN (0.6)
37*77b80299SAndroid Build Coastguard Worker
38*77b80299SAndroid Build Coastguard Worker // the precision used for cout to dump float
39*77b80299SAndroid Build Coastguard Worker #define DUMP_PRICISION 2
40*77b80299SAndroid Build Coastguard Worker
41*77b80299SAndroid Build Coastguard Worker using std::cerr;
42*77b80299SAndroid Build Coastguard Worker using std::cout;
43*77b80299SAndroid Build Coastguard Worker using std::endl;
44*77b80299SAndroid Build Coastguard Worker using std::left;
45*77b80299SAndroid Build Coastguard Worker using std::ios;
46*77b80299SAndroid Build Coastguard Worker using std::min;
47*77b80299SAndroid Build Coastguard Worker using std::max;
48*77b80299SAndroid Build Coastguard Worker using std::to_string;
49*77b80299SAndroid Build Coastguard Worker using std::setprecision;
50*77b80299SAndroid Build Coastguard Worker using std::setw;
51*77b80299SAndroid Build Coastguard Worker using std::ofstream;
52*77b80299SAndroid Build Coastguard Worker using std::make_tuple;
53*77b80299SAndroid Build Coastguard Worker
createPipePair()54*77b80299SAndroid Build Coastguard Worker tuple<Pipe, Pipe> Pipe::createPipePair() {
55*77b80299SAndroid Build Coastguard Worker int a[2];
56*77b80299SAndroid Build Coastguard Worker int b[2];
57*77b80299SAndroid Build Coastguard Worker
58*77b80299SAndroid Build Coastguard Worker int error1 = pipe(a);
59*77b80299SAndroid Build Coastguard Worker int error2 = pipe(b);
60*77b80299SAndroid Build Coastguard Worker ASSERT(error1 >= 0);
61*77b80299SAndroid Build Coastguard Worker ASSERT(error2 >= 0);
62*77b80299SAndroid Build Coastguard Worker
63*77b80299SAndroid Build Coastguard Worker return make_tuple(Pipe(a[0], b[1]), Pipe(b[0], a[1]));
64*77b80299SAndroid Build Coastguard Worker }
65*77b80299SAndroid Build Coastguard Worker
Pipe(Pipe && rval)66*77b80299SAndroid Build Coastguard Worker Pipe::Pipe(Pipe&& rval) noexcept {
67*77b80299SAndroid Build Coastguard Worker fd_read_ = rval.fd_read_;
68*77b80299SAndroid Build Coastguard Worker fd_write_ = rval.fd_write_;
69*77b80299SAndroid Build Coastguard Worker rval.fd_read_ = 0;
70*77b80299SAndroid Build Coastguard Worker rval.fd_write_ = 0;
71*77b80299SAndroid Build Coastguard Worker }
72*77b80299SAndroid Build Coastguard Worker
~Pipe()73*77b80299SAndroid Build Coastguard Worker Pipe::~Pipe() {
74*77b80299SAndroid Build Coastguard Worker if (fd_read_) {
75*77b80299SAndroid Build Coastguard Worker close(fd_read_);
76*77b80299SAndroid Build Coastguard Worker }
77*77b80299SAndroid Build Coastguard Worker if (fd_write_) {
78*77b80299SAndroid Build Coastguard Worker close(fd_write_);
79*77b80299SAndroid Build Coastguard Worker }
80*77b80299SAndroid Build Coastguard Worker }
81*77b80299SAndroid Build Coastguard Worker
combine(const Results & a,const Results & b)82*77b80299SAndroid Build Coastguard Worker Results Results::combine(const Results& a, const Results& b) {
83*77b80299SAndroid Build Coastguard Worker Results ret;
84*77b80299SAndroid Build Coastguard Worker for (uint32_t i = 0; i < kNumBuckets; i++) {
85*77b80299SAndroid Build Coastguard Worker ret.buckets_[i] = a.buckets_[i] + b.buckets_[i];
86*77b80299SAndroid Build Coastguard Worker }
87*77b80299SAndroid Build Coastguard Worker ret.worst_ = max(a.worst_, b.worst_);
88*77b80299SAndroid Build Coastguard Worker ret.best_ = min(a.best_, b.best_);
89*77b80299SAndroid Build Coastguard Worker ret.transactions_ = a.transactions_ + b.transactions_;
90*77b80299SAndroid Build Coastguard Worker ret.miss_ = a.miss_ + b.miss_;
91*77b80299SAndroid Build Coastguard Worker ret.total_time_ = a.total_time_ + b.total_time_;
92*77b80299SAndroid Build Coastguard Worker return ret;
93*77b80299SAndroid Build Coastguard Worker }
94*77b80299SAndroid Build Coastguard Worker
traceStop()95*77b80299SAndroid Build Coastguard Worker static void traceStop() {
96*77b80299SAndroid Build Coastguard Worker ofstream file;
97*77b80299SAndroid Build Coastguard Worker file.open(TRACE_PATH "/tracing_on", ios::out | ios::trunc);
98*77b80299SAndroid Build Coastguard Worker file << '0' << endl;
99*77b80299SAndroid Build Coastguard Worker file.close();
100*77b80299SAndroid Build Coastguard Worker }
101*77b80299SAndroid Build Coastguard Worker
addTime(uint64_t nano)102*77b80299SAndroid Build Coastguard Worker void Results::addTime(uint64_t nano) {
103*77b80299SAndroid Build Coastguard Worker buckets_[min(nano, kMaxTimeBucket - 1) / kTimePerBucket] += 1;
104*77b80299SAndroid Build Coastguard Worker best_ = min(nano, best_);
105*77b80299SAndroid Build Coastguard Worker worst_ = max(nano, worst_);
106*77b80299SAndroid Build Coastguard Worker if (raw_dump_) {
107*77b80299SAndroid Build Coastguard Worker raw_data_->push_back(nano);
108*77b80299SAndroid Build Coastguard Worker }
109*77b80299SAndroid Build Coastguard Worker transactions_ += 1;
110*77b80299SAndroid Build Coastguard Worker total_time_ += nano;
111*77b80299SAndroid Build Coastguard Worker if (missDeadline(nano)) {
112*77b80299SAndroid Build Coastguard Worker miss_++;
113*77b80299SAndroid Build Coastguard Worker if (tracing_) {
114*77b80299SAndroid Build Coastguard Worker // There might be multiple process pair running the test concurrently
115*77b80299SAndroid Build Coastguard Worker // each may execute following statements and only the first one actually
116*77b80299SAndroid Build Coastguard Worker // stop the trace and any traceStop() after then has no effect.
117*77b80299SAndroid Build Coastguard Worker traceStop();
118*77b80299SAndroid Build Coastguard Worker cerr << endl;
119*77b80299SAndroid Build Coastguard Worker cerr << "deadline triggered: halt & stop trace" << endl;
120*77b80299SAndroid Build Coastguard Worker cerr << "log:" TRACE_PATH "/trace" << endl;
121*77b80299SAndroid Build Coastguard Worker cerr << endl;
122*77b80299SAndroid Build Coastguard Worker exit(EXIT_FAILURE);
123*77b80299SAndroid Build Coastguard Worker }
124*77b80299SAndroid Build Coastguard Worker }
125*77b80299SAndroid Build Coastguard Worker }
126*77b80299SAndroid Build Coastguard Worker
setupRawData()127*77b80299SAndroid Build Coastguard Worker void Results::setupRawData() {
128*77b80299SAndroid Build Coastguard Worker raw_dump_ = true;
129*77b80299SAndroid Build Coastguard Worker if (raw_data_ == nullptr) {
130*77b80299SAndroid Build Coastguard Worker raw_data_ = new list<uint64_t>;
131*77b80299SAndroid Build Coastguard Worker } else {
132*77b80299SAndroid Build Coastguard Worker raw_data_->clear();
133*77b80299SAndroid Build Coastguard Worker }
134*77b80299SAndroid Build Coastguard Worker }
135*77b80299SAndroid Build Coastguard Worker
flushRawData()136*77b80299SAndroid Build Coastguard Worker void Results::flushRawData() {
137*77b80299SAndroid Build Coastguard Worker if (raw_dump_) {
138*77b80299SAndroid Build Coastguard Worker bool first = true;
139*77b80299SAndroid Build Coastguard Worker cout << "[";
140*77b80299SAndroid Build Coastguard Worker for (auto nano : *raw_data_) {
141*77b80299SAndroid Build Coastguard Worker cout << (first ? "" : ",") << to_string(nano);
142*77b80299SAndroid Build Coastguard Worker first = false;
143*77b80299SAndroid Build Coastguard Worker }
144*77b80299SAndroid Build Coastguard Worker cout << "]," << endl;
145*77b80299SAndroid Build Coastguard Worker delete raw_data_;
146*77b80299SAndroid Build Coastguard Worker raw_data_ = nullptr;
147*77b80299SAndroid Build Coastguard Worker }
148*77b80299SAndroid Build Coastguard Worker }
149*77b80299SAndroid Build Coastguard Worker
dump() const150*77b80299SAndroid Build Coastguard Worker void Results::dump() const {
151*77b80299SAndroid Build Coastguard Worker double best = (double)best_ / 1.0E6;
152*77b80299SAndroid Build Coastguard Worker double worst = (double)worst_ / 1.0E6;
153*77b80299SAndroid Build Coastguard Worker double average = (double)total_time_ / transactions_ / 1.0E6;
154*77b80299SAndroid Build Coastguard Worker int W = DUMP_PRICISION + 2;
155*77b80299SAndroid Build Coastguard Worker cout << std::setprecision(DUMP_PRICISION) << "{ \"avg\":" << setw(W) << left << average
156*77b80299SAndroid Build Coastguard Worker << ", \"wst\":" << setw(W) << left << worst << ", \"bst\":" << setw(W) << left << best
157*77b80299SAndroid Build Coastguard Worker << ", \"miss\":" << left << miss_ << ", \"meetR\":" << setprecision(DUMP_PRICISION + 3)
158*77b80299SAndroid Build Coastguard Worker << left << (1.0 - (double)miss_ / transactions_) << "}";
159*77b80299SAndroid Build Coastguard Worker }
160*77b80299SAndroid Build Coastguard Worker
dumpDistribution() const161*77b80299SAndroid Build Coastguard Worker void Results::dumpDistribution() const {
162*77b80299SAndroid Build Coastguard Worker uint64_t cur_total = 0;
163*77b80299SAndroid Build Coastguard Worker cout << "{ ";
164*77b80299SAndroid Build Coastguard Worker cout << std::setprecision(DUMP_PRICISION + 3);
165*77b80299SAndroid Build Coastguard Worker for (uint32_t i = 0; i < kNumBuckets; i++) {
166*77b80299SAndroid Build Coastguard Worker float cur_time = kTimePerBucketMS * i + 0.5f * kTimePerBucketMS;
167*77b80299SAndroid Build Coastguard Worker float accumulation = cur_total + buckets_[i];
168*77b80299SAndroid Build Coastguard Worker if ((cur_total < 0.5f * transactions_) && (accumulation >= 0.5f * transactions_)) {
169*77b80299SAndroid Build Coastguard Worker cout << "\"p50\":" << cur_time << ", ";
170*77b80299SAndroid Build Coastguard Worker }
171*77b80299SAndroid Build Coastguard Worker if ((cur_total < 0.9f * transactions_) && (accumulation >= 0.9f * transactions_)) {
172*77b80299SAndroid Build Coastguard Worker cout << "\"p90\":" << cur_time << ", ";
173*77b80299SAndroid Build Coastguard Worker }
174*77b80299SAndroid Build Coastguard Worker if ((cur_total < 0.95f * transactions_) && (accumulation >= 0.95f * transactions_)) {
175*77b80299SAndroid Build Coastguard Worker cout << "\"p95\":" << cur_time << ", ";
176*77b80299SAndroid Build Coastguard Worker }
177*77b80299SAndroid Build Coastguard Worker if ((cur_total < 0.99f * transactions_) && (accumulation >= 0.99f * transactions_)) {
178*77b80299SAndroid Build Coastguard Worker cout << "\"p99\": " << cur_time;
179*77b80299SAndroid Build Coastguard Worker }
180*77b80299SAndroid Build Coastguard Worker cur_total += buckets_[i];
181*77b80299SAndroid Build Coastguard Worker }
182*77b80299SAndroid Build Coastguard Worker cout << "}";
183*77b80299SAndroid Build Coastguard Worker }
184*77b80299SAndroid Build Coastguard Worker
combine(const PResults & a,const PResults & b)185*77b80299SAndroid Build Coastguard Worker PResults PResults::combine(const PResults& a, const PResults& b) {
186*77b80299SAndroid Build Coastguard Worker PResults ret;
187*77b80299SAndroid Build Coastguard Worker ret.nNotInherent = a.nNotInherent + b.nNotInherent;
188*77b80299SAndroid Build Coastguard Worker ret.nNotSync = a.nNotSync + b.nNotSync;
189*77b80299SAndroid Build Coastguard Worker ret.other = Results::combine(a.other, b.other);
190*77b80299SAndroid Build Coastguard Worker ret.fifo = Results::combine(a.fifo, b.fifo);
191*77b80299SAndroid Build Coastguard Worker return ret;
192*77b80299SAndroid Build Coastguard Worker }
193*77b80299SAndroid Build Coastguard Worker
dump() const194*77b80299SAndroid Build Coastguard Worker void PResults::dump() const {
195*77b80299SAndroid Build Coastguard Worker int no_trans = other.getTransactions() + fifo.getTransactions();
196*77b80299SAndroid Build Coastguard Worker double sync_ratio = (1.0 - (double)nNotSync / no_trans);
197*77b80299SAndroid Build Coastguard Worker cout << "{\"SYNC\":\"" << ((sync_ratio > GOOD_SYNC_MIN) ? "GOOD" : "POOR") << "\","
198*77b80299SAndroid Build Coastguard Worker << "\"S\":" << (no_trans - nNotSync) << ",\"I\":" << no_trans << ","
199*77b80299SAndroid Build Coastguard Worker << "\"R\":" << sync_ratio << "," << endl;
200*77b80299SAndroid Build Coastguard Worker cout << " \"other_ms\":";
201*77b80299SAndroid Build Coastguard Worker other.dump();
202*77b80299SAndroid Build Coastguard Worker cout << "," << endl;
203*77b80299SAndroid Build Coastguard Worker cout << " \"fifo_ms\": ";
204*77b80299SAndroid Build Coastguard Worker fifo.dump();
205*77b80299SAndroid Build Coastguard Worker cout << "," << endl;
206*77b80299SAndroid Build Coastguard Worker cout << " \"otherdis\":";
207*77b80299SAndroid Build Coastguard Worker other.dumpDistribution();
208*77b80299SAndroid Build Coastguard Worker cout << "," << endl;
209*77b80299SAndroid Build Coastguard Worker cout << " \"fifodis\": ";
210*77b80299SAndroid Build Coastguard Worker fifo.dumpDistribution();
211*77b80299SAndroid Build Coastguard Worker cout << endl;
212*77b80299SAndroid Build Coastguard Worker cout << "}," << endl;
213*77b80299SAndroid Build Coastguard Worker }
214