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 #ifndef HWBINDER_PERF_TEST_H
17*77b80299SAndroid Build Coastguard Worker #define HWBINDER_PERF_TEST_H
18*77b80299SAndroid Build Coastguard Worker
19*77b80299SAndroid Build Coastguard Worker #include <unistd.h>
20*77b80299SAndroid Build Coastguard Worker #include <chrono>
21*77b80299SAndroid Build Coastguard Worker #include <list>
22*77b80299SAndroid Build Coastguard Worker #include <tuple>
23*77b80299SAndroid Build Coastguard Worker
24*77b80299SAndroid Build Coastguard Worker #define TRACE_PATH "/sys/kernel/debug/tracing"
25*77b80299SAndroid Build Coastguard Worker
26*77b80299SAndroid Build Coastguard Worker using std::list;
27*77b80299SAndroid Build Coastguard Worker using std::tuple;
28*77b80299SAndroid Build Coastguard Worker
29*77b80299SAndroid Build Coastguard Worker // Pipe is a object used for IPC between parent process and child process.
30*77b80299SAndroid Build Coastguard Worker // This IPC class is widely used in binder/hwbinder tests.
31*77b80299SAndroid Build Coastguard Worker // The common usage is the main process to create the Pipe and forks.
32*77b80299SAndroid Build Coastguard Worker // Both parent and child hold a object. Each recv() on one side requires
33*77b80299SAndroid Build Coastguard Worker // a send() on the other side to unblock.
34*77b80299SAndroid Build Coastguard Worker class Pipe {
35*77b80299SAndroid Build Coastguard Worker public:
36*77b80299SAndroid Build Coastguard Worker static tuple<Pipe, Pipe> createPipePair();
37*77b80299SAndroid Build Coastguard Worker Pipe(Pipe&& rval) noexcept;
38*77b80299SAndroid Build Coastguard Worker ~Pipe();
signal()39*77b80299SAndroid Build Coastguard Worker inline void signal() {
40*77b80299SAndroid Build Coastguard Worker bool val = true;
41*77b80299SAndroid Build Coastguard Worker send(val);
42*77b80299SAndroid Build Coastguard Worker }
wait()43*77b80299SAndroid Build Coastguard Worker inline void wait() {
44*77b80299SAndroid Build Coastguard Worker bool val = false;
45*77b80299SAndroid Build Coastguard Worker recv(val);
46*77b80299SAndroid Build Coastguard Worker }
47*77b80299SAndroid Build Coastguard Worker
48*77b80299SAndroid Build Coastguard Worker // write a data struct
49*77b80299SAndroid Build Coastguard Worker template <typename T>
send(const T & v)50*77b80299SAndroid Build Coastguard Worker int send(const T& v) {
51*77b80299SAndroid Build Coastguard Worker return write(fd_write_, &v, sizeof(T));
52*77b80299SAndroid Build Coastguard Worker }
53*77b80299SAndroid Build Coastguard Worker // read a data struct
54*77b80299SAndroid Build Coastguard Worker template <typename T>
recv(T & v)55*77b80299SAndroid Build Coastguard Worker int recv(T& v) {
56*77b80299SAndroid Build Coastguard Worker return read(fd_read_, &v, sizeof(T));
57*77b80299SAndroid Build Coastguard Worker }
58*77b80299SAndroid Build Coastguard Worker
59*77b80299SAndroid Build Coastguard Worker private:
60*77b80299SAndroid Build Coastguard Worker int fd_read_; // file descriptor to read
61*77b80299SAndroid Build Coastguard Worker int fd_write_; // file descriptor to write
Pipe(int read_fd,int write_fd)62*77b80299SAndroid Build Coastguard Worker Pipe(int read_fd, int write_fd) : fd_read_{read_fd}, fd_write_{write_fd} {}
63*77b80299SAndroid Build Coastguard Worker Pipe(const Pipe&) = delete;
64*77b80299SAndroid Build Coastguard Worker Pipe& operator=(const Pipe&) = delete;
65*77b80299SAndroid Build Coastguard Worker Pipe& operator=(const Pipe&&) = delete;
66*77b80299SAndroid Build Coastguard Worker };
67*77b80299SAndroid Build Coastguard Worker
68*77b80299SAndroid Build Coastguard Worker // statistics of latency
69*77b80299SAndroid Build Coastguard Worker // common usage:
70*77b80299SAndroid Build Coastguard Worker //
71*77b80299SAndroid Build Coastguard Worker // Results r;
72*77b80299SAndroid Build Coastguard Worker // Tick sta, end;
73*77b80299SAndroid Build Coastguard Worker // TICK_NOW(sta);
74*77b80299SAndroid Build Coastguard Worker // ... do something ...
75*77b80299SAndroid Build Coastguard Worker // TICK_NOW(end);
76*77b80299SAndroid Build Coastguard Worker // r.addTime(tickDiffNS(sta, end));
77*77b80299SAndroid Build Coastguard Worker //
78*77b80299SAndroid Build Coastguard Worker // r.dump();
79*77b80299SAndroid Build Coastguard Worker // r.dumpDistribution();
80*77b80299SAndroid Build Coastguard Worker //
81*77b80299SAndroid Build Coastguard Worker class Results {
82*77b80299SAndroid Build Coastguard Worker public:
83*77b80299SAndroid Build Coastguard Worker // enable the deadline miss detection which stops the trace recording after
84*77b80299SAndroid Build Coastguard Worker // a transaction latency > deadline_us_ is detected.
setTracingMode(bool tracing,uint64_t deadline_us)85*77b80299SAndroid Build Coastguard Worker void setTracingMode(bool tracing, uint64_t deadline_us) {
86*77b80299SAndroid Build Coastguard Worker tracing_ = tracing;
87*77b80299SAndroid Build Coastguard Worker deadline_us_ = deadline_us;
88*77b80299SAndroid Build Coastguard Worker }
getTransactions()89*77b80299SAndroid Build Coastguard Worker inline uint64_t getTransactions() const { return transactions_; }
missDeadline(uint64_t nano)90*77b80299SAndroid Build Coastguard Worker inline bool missDeadline(uint64_t nano) const { return nano > deadline_us_ * 1000; }
91*77b80299SAndroid Build Coastguard Worker // Combine two sets of latency data points and update the aggregation info.
92*77b80299SAndroid Build Coastguard Worker static Results combine(const Results& a, const Results& b);
93*77b80299SAndroid Build Coastguard Worker // add a new transaction latency record
94*77b80299SAndroid Build Coastguard Worker void addTime(uint64_t nano);
95*77b80299SAndroid Build Coastguard Worker // prepare for raw data recording, it may allocate resources which requires
96*77b80299SAndroid Build Coastguard Worker // a flushRawData() to release
97*77b80299SAndroid Build Coastguard Worker void setupRawData();
98*77b80299SAndroid Build Coastguard Worker // dump the raw data and release the resource
99*77b80299SAndroid Build Coastguard Worker void flushRawData();
100*77b80299SAndroid Build Coastguard Worker // dump average, best, worst latency in json
101*77b80299SAndroid Build Coastguard Worker void dump() const;
102*77b80299SAndroid Build Coastguard Worker // dump latency distribution in json
103*77b80299SAndroid Build Coastguard Worker void dumpDistribution() const;
104*77b80299SAndroid Build Coastguard Worker
105*77b80299SAndroid Build Coastguard Worker private:
106*77b80299SAndroid Build Coastguard Worker static const uint32_t kNumBuckets = 128;
107*77b80299SAndroid Build Coastguard Worker static const uint64_t kMaxTimeBucket = 50ull * 1000000;
108*77b80299SAndroid Build Coastguard Worker static const uint64_t kTimePerBucket = kMaxTimeBucket / kNumBuckets;
109*77b80299SAndroid Build Coastguard Worker static constexpr float kTimePerBucketMS = kTimePerBucket / 1.0E6;
110*77b80299SAndroid Build Coastguard Worker uint64_t best_ = 0xffffffffffffffffULL; // best transaction latency in ns.
111*77b80299SAndroid Build Coastguard Worker uint64_t worst_ = 0; // worst transaction latency in ns.
112*77b80299SAndroid Build Coastguard Worker uint64_t transactions_ = 0; // number of transactions
113*77b80299SAndroid Build Coastguard Worker uint64_t total_time_ = 0; // total transaction time
114*77b80299SAndroid Build Coastguard Worker uint64_t miss_ = 0; // number of transactions whose latency > deadline
115*77b80299SAndroid Build Coastguard Worker uint32_t buckets_[kNumBuckets] = {0}; // statistics for the distribution
116*77b80299SAndroid Build Coastguard Worker list<uint64_t>* raw_data_ = nullptr; // list for raw-data
117*77b80299SAndroid Build Coastguard Worker bool tracing_ = false; // halt the trace log on a deadline miss
118*77b80299SAndroid Build Coastguard Worker bool raw_dump_ = false; // record the raw data for the dump after
119*77b80299SAndroid Build Coastguard Worker uint64_t deadline_us_ = 2500; // latency deadline in us.
120*77b80299SAndroid Build Coastguard Worker };
121*77b80299SAndroid Build Coastguard Worker
122*77b80299SAndroid Build Coastguard Worker // statistics of a process pair
123*77b80299SAndroid Build Coastguard Worker class PResults {
124*77b80299SAndroid Build Coastguard Worker public:
125*77b80299SAndroid Build Coastguard Worker static PResults combine(const PResults& a, const PResults& b);
126*77b80299SAndroid Build Coastguard Worker int nNotInherent = 0; ///< #transactions that does not inherit priority
127*77b80299SAndroid Build Coastguard Worker int nNotSync = 0; ///< #transactions that are not synced
128*77b80299SAndroid Build Coastguard Worker Results other; ///< statistics of CFS-other transactions
129*77b80299SAndroid Build Coastguard Worker Results fifo; ///< statistics of RT-fifo transactions
130*77b80299SAndroid Build Coastguard Worker // dump and flush the raw data
flushRawData()131*77b80299SAndroid Build Coastguard Worker inline void flushRawData() { fifo.flushRawData(); }
132*77b80299SAndroid Build Coastguard Worker // dump in json
133*77b80299SAndroid Build Coastguard Worker void dump() const;
134*77b80299SAndroid Build Coastguard Worker };
135*77b80299SAndroid Build Coastguard Worker
136*77b80299SAndroid Build Coastguard Worker // Tick keeps timestamp
137*77b80299SAndroid Build Coastguard Worker typedef std::chrono::time_point<std::chrono::high_resolution_clock> Tick;
138*77b80299SAndroid Build Coastguard Worker
139*77b80299SAndroid Build Coastguard Worker // get current timestamp as a Tick
tickNow()140*77b80299SAndroid Build Coastguard Worker static inline Tick tickNow() {
141*77b80299SAndroid Build Coastguard Worker return std::chrono::high_resolution_clock::now();
142*77b80299SAndroid Build Coastguard Worker }
143*77b80299SAndroid Build Coastguard Worker
144*77b80299SAndroid Build Coastguard Worker #define TICK_NOW(_tick) \
145*77b80299SAndroid Build Coastguard Worker do { \
146*77b80299SAndroid Build Coastguard Worker asm volatile("" ::: "memory"); \
147*77b80299SAndroid Build Coastguard Worker _tick = tickNow(); \
148*77b80299SAndroid Build Coastguard Worker asm volatile("" ::: "memory"); \
149*77b80299SAndroid Build Coastguard Worker } while (0)
150*77b80299SAndroid Build Coastguard Worker
151*77b80299SAndroid Build Coastguard Worker // get nano seconds between sta & end
tickDiffNS(Tick & sta,Tick & end)152*77b80299SAndroid Build Coastguard Worker static inline uint64_t tickDiffNS(Tick& sta, Tick& end) {
153*77b80299SAndroid Build Coastguard Worker return uint64_t(std::chrono::duration_cast<std::chrono::nanoseconds>(end - sta).count());
154*77b80299SAndroid Build Coastguard Worker }
155*77b80299SAndroid Build Coastguard Worker #endif
156