xref: /aosp_15_r20/system/libhwbinder/vts/performance/PerfTest.h (revision 77b80299c8bdfeca3ae6d0ce27ae1ad3db289be3)
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