1 /*
2  * Copyright (C) 2019 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 #ifndef _IO_USAGE_H_
17 #define _IO_USAGE_H_
18 
19 #include <statstype.h>
20 #include <chrono>
21 #include <sstream>
22 #include <string>
23 
24 #include <unordered_map>
25 
26 #define IO_USAGE_BUFFER_SIZE (6 * 30)
27 #define IO_TOP_MAX 5
28 
29 namespace android {
30 namespace pixel {
31 namespace perfstatsd {
32 
33 class ProcPidIoStats {
34   private:
35     std::chrono::system_clock::time_point mCheckTime;
36     std::vector<uint32_t> mPrevPids;
37     std::vector<uint32_t> mCurrPids;
38     std::unordered_map<uint32_t, std::string> mUidNameMapping;
39     // functions
40     std::vector<uint32_t> getNewPids();
41 
42   public:
43     void update(bool forceAll);
44     bool getNameForUid(uint32_t uid, std::string *name);
45 };
46 
47 struct UserIo {
48     uint32_t uid;
49     uint64_t fgRead;
50     uint64_t bgRead;
51     uint64_t fgWrite;
52     uint64_t bgWrite;
53     uint64_t fgFsync;
54     uint64_t bgFsync;
55 
56     UserIo &operator=(const UserIo &other) {
57         uid = other.uid;
58         fgRead = other.fgRead;
59         bgRead = other.bgRead;
60         fgWrite = other.fgWrite;
61         bgWrite = other.bgWrite;
62         fgFsync = other.fgFsync;
63         bgFsync = other.bgFsync;
64         return *this;
65     }
66 
67     UserIo operator-(const UserIo &other) const {
68         UserIo r;
69         r.uid = uid;
70         r.fgRead = fgRead - other.fgRead;
71         r.bgRead = bgRead - other.bgRead;
72         r.fgWrite = fgWrite - other.fgWrite;
73         r.bgWrite = bgWrite - other.bgWrite;
74         r.fgFsync = fgFsync - other.fgFsync;
75         r.bgFsync = bgFsync - other.bgFsync;
76         return r;
77     }
78 
79     UserIo operator+(const UserIo &other) const {
80         UserIo r;
81         r.uid = uid;
82         r.fgRead = fgRead + other.fgRead;
83         r.bgRead = bgRead + other.bgRead;
84         r.fgWrite = fgWrite + other.fgWrite;
85         r.bgWrite = bgWrite + other.bgWrite;
86         r.fgFsync = fgFsync + other.fgFsync;
87         r.bgFsync = bgFsync + other.bgFsync;
88         return r;
89     }
90 
sumWriteUserIo91     uint64_t sumWrite() { return fgWrite + bgWrite; }
92 
sumReadUserIo93     uint64_t sumRead() { return fgRead + bgRead; }
94 
resetUserIo95     void reset() {
96         uid = 0;
97         fgRead = 0;
98         bgRead = 0;
99         fgWrite = 0;
100         bgWrite = 0;
101         fgFsync = 0;
102         bgFsync = 0;
103     }
104 };
105 
106 class ScopeTimer {
107   private:
108     bool mDisabled;
109     std::string mName;
110     std::chrono::system_clock::time_point mStart;
111 
112   public:
ScopeTimer()113     ScopeTimer() : ScopeTimer("") {}
ScopeTimer(std::string name)114     ScopeTimer(std::string name) : mDisabled(false), mName(name) {
115         mStart = std::chrono::system_clock::now();
116     }
~ScopeTimer()117     ~ScopeTimer() {
118         if (!mDisabled) {
119             std::string msg;
120             dump(&msg);
121             LOG(INFO) << msg;
122         }
123     }
setEnabled(bool enabled)124     void setEnabled(bool enabled) { mDisabled = !enabled; }
125     void dump(std::string *outAppend);
126 };
127 
128 constexpr uint64_t IO_USAGE_DUMP_THRESHOLD = 50L * 1000L * 1000L;  // 50MB
129 class IoStats {
130   private:
131     uint64_t mMinSizeOfTotalRead = IO_USAGE_DUMP_THRESHOLD;
132     uint64_t mMinSizeOfTotalWrite = IO_USAGE_DUMP_THRESHOLD;
133     std::chrono::system_clock::time_point mLast;
134     std::chrono::system_clock::time_point mNow;
135     std::unordered_map<uint32_t, UserIo> mPrevious;
136     UserIo mTotal;
137     UserIo mWriteTop[IO_TOP_MAX];
138     UserIo mReadTop[IO_TOP_MAX];
139     std::vector<uint32_t> mUnknownUidList;
140     std::unordered_map<uint32_t, std::string> mUidNameMap;
141     ProcPidIoStats mProcIoStats;
142     // Functions
143     std::unordered_map<uint32_t, UserIo> calcIncrement(
144         const std::unordered_map<uint32_t, UserIo> &data);
145     void updateTopWrite(UserIo usage);
146     void updateTopRead(UserIo usage);
147     void updateUnknownUidList();
148 
149   public:
IoStats()150     IoStats() {
151         mNow = std::chrono::system_clock::now();
152         mLast = mNow;
153     }
154     void calcAll(std::unordered_map<uint32_t, UserIo> &&data);
setDumpThresholdSizeForRead(uint64_t size)155     void setDumpThresholdSizeForRead(uint64_t size) { mMinSizeOfTotalRead = size; }
setDumpThresholdSizeForWrite(uint64_t size)156     void setDumpThresholdSizeForWrite(uint64_t size) { mMinSizeOfTotalWrite = size; }
157     bool dump(std::stringstream *output);
158 };
159 
160 class IoUsage : public StatsType {
161   private:
162     bool mDisabled;
163     IoStats mStats;
164 
165   public:
IoUsage()166     IoUsage() : mDisabled(false) {}
167     void refresh(void);
168     void setOptions(const std::string &key, const std::string &value);
169 };
170 
171 }  // namespace perfstatsd
172 }  // namespace pixel
173 }  // namespace android
174 
175 #endif /*  _IO_USAGE_H_ */
176