• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2020, 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 #ifndef CPP_WATCHDOG_SERVER_SRC_IOPERFCOLLECTION_H_
18 #define CPP_WATCHDOG_SERVER_SRC_IOPERFCOLLECTION_H_
19 
20 #include "PackageInfoResolver.h"
21 #include "ProcDiskStats.h"
22 #include "ProcPidStat.h"
23 #include "ProcStat.h"
24 #include "UidIoStats.h"
25 #include "WatchdogPerfService.h"
26 
27 #include <android-base/result.h>
28 #include <cutils/multiuser.h>
29 #include <gtest/gtest_prod.h>
30 #include <utils/Errors.h>
31 #include <utils/Mutex.h>
32 #include <utils/RefBase.h>
33 
34 #include <ctime>
35 #include <string>
36 #include <unordered_set>
37 #include <vector>
38 
39 namespace android {
40 namespace automotive {
41 namespace watchdog {
42 
43 // Number of periodic collection perf data snapshots to cache in memory.
44 const int32_t kDefaultPeriodicCollectionBufferSize = 180;
45 constexpr const char* kEmptyCollectionMessage = "No collection recorded\n";
46 
47 // Performance data collected from the `/proc/uid_io/stats` file.
48 struct UidIoPerfData {
49     struct Stats {
50         userid_t userId = 0;
51         std::string packageName;
52         int64_t bytes[UID_STATES];
53         int64_t fsync[UID_STATES];
54     };
55     std::vector<Stats> topNReads = {};
56     std::vector<Stats> topNWrites = {};
57     int64_t total[METRIC_TYPES][UID_STATES] = {{0}};
58 };
59 
60 std::string toString(const UidIoPerfData& perfData);
61 
62 // Performance data collected from the `/proc/stats` file.
63 struct SystemIoPerfData {
64     uint64_t cpuIoWaitTime = 0;
65     uint64_t totalCpuTime = 0;
66     uint32_t ioBlockedProcessesCnt = 0;
67     uint32_t totalProcessesCnt = 0;
68 };
69 
70 std::string toString(const SystemIoPerfData& perfData);
71 
72 // Performance data collected from the `/proc/[pid]/stat` and `/proc/[pid]/task/[tid]/stat` files.
73 struct ProcessIoPerfData {
74     struct UidStats {
75         userid_t userId = 0;
76         std::string packageName;
77         uint64_t count = 0;
78         struct ProcessStats {
79             std::string comm = "";
80             uint64_t count = 0;
81         };
82         std::vector<ProcessStats> topNProcesses = {};
83     };
84     std::vector<UidStats> topNIoBlockedUids = {};
85     // Total # of tasks owned by each UID in |topNIoBlockedUids|.
86     std::vector<uint64_t> topNIoBlockedUidsTotalTaskCnt = {};
87     std::vector<UidStats> topNMajorFaultUids = {};
88     uint64_t totalMajorFaults = 0;
89     // Percentage of increase/decrease in the major page faults since last collection.
90     double majorFaultsPercentChange = 0.0;
91 };
92 
93 std::string toString(const ProcessIoPerfData& data);
94 
95 struct IoPerfRecord {
96     time_t time;  // Collection time.
97     UidIoPerfData uidIoPerfData;
98     SystemIoPerfData systemIoPerfData;
99     ProcessIoPerfData processIoPerfData;
100 };
101 
102 std::string toString(const IoPerfRecord& record);
103 
104 struct CollectionInfo {
105     size_t maxCacheSize = 0;            // Maximum cache size for the collection.
106     std::vector<IoPerfRecord> records;  // Cache of collected performance records.
107 };
108 
109 std::string toString(const CollectionInfo& collectionInfo);
110 
111 // Forward declaration for testing use only.
112 namespace internal {
113 
114 class IoPerfCollectionPeer;
115 
116 }  // namespace internal
117 
118 // IoPerfCollection implements the I/O performance data collection module.
119 class IoPerfCollection : public IDataProcessorInterface {
120 public:
IoPerfCollection()121     IoPerfCollection() :
122           mTopNStatsPerCategory(0),
123           mTopNStatsPerSubcategory(0),
124           mPackageInfoResolver(PackageInfoResolver::getInstance()),
125           mBoottimeCollection({}),
126           mPeriodicCollection({}),
127           mCustomCollection({}),
128           mLastMajorFaults(0) {}
129 
~IoPerfCollection()130     ~IoPerfCollection() { terminate(); }
131 
name()132     std::string name() { return "IoPerfCollection"; }
133 
134     // Implements IDataProcessorInterface.
135     android::base::Result<void> onBoottimeCollection(time_t time,
136                                                      const android::wp<UidIoStats>& uidIoStats,
137                                                      const android::wp<ProcStat>& procStat,
138                                                      const android::wp<ProcPidStat>& procPidStat);
139 
140     android::base::Result<void> onPeriodicCollection(time_t time, SystemState systemState,
141                                                      const android::wp<UidIoStats>& uidIoStats,
142                                                      const android::wp<ProcStat>& procStat,
143                                                      const android::wp<ProcPidStat>& procPidStat);
144 
145     android::base::Result<void> onCustomCollection(
146             time_t time, SystemState systemState,
147             const std::unordered_set<std::string>& filterPackages,
148             const android::wp<UidIoStats>& uidIoStats, const android::wp<ProcStat>& procStat,
149             const android::wp<ProcPidStat>& procPidStat);
150 
onPeriodicMonitor(time_t time,const android::wp<IProcDiskStatsInterface> & procDiskStats,const std::function<void ()> & alertHandler)151     android::base::Result<void> onPeriodicMonitor(
152             [[maybe_unused]] time_t time,
153             [[maybe_unused]] const android::wp<IProcDiskStatsInterface>& procDiskStats,
154             [[maybe_unused]] const std::function<void()>& alertHandler) {
155         // No monitoring done here as this DataProcessor only collects I/O performance records.
156         return {};
157     }
158 
159     android::base::Result<void> onDump(int fd);
160 
161     android::base::Result<void> onCustomCollectionDump(int fd);
162 
163 protected:
164     android::base::Result<void> init();
165 
166     // Clears in-memory cache.
167     void terminate();
168 
169 private:
170     // Processes the collected data.
171     android::base::Result<void> processLocked(time_t time,
172                                               const std::unordered_set<std::string>& filterPackages,
173                                               const android::wp<UidIoStats>& uidIoStats,
174                                               const android::wp<ProcStat>& procStat,
175                                               const android::wp<ProcPidStat>& procPidStat,
176                                               CollectionInfo* collectionInfo);
177 
178     // Processes performance data from the `/proc/uid_io/stats` file.
179     void processUidIoPerfData(const std::unordered_set<std::string>& filterPackages,
180                               const android::wp<UidIoStats>& uidIoStats,
181                               UidIoPerfData* uidIoPerfData) const;
182 
183     // Processes performance data from the `/proc/stats` file.
184     void processSystemIoPerfData(const android::wp<ProcStat>& procStat,
185                                  SystemIoPerfData* systemIoPerfData) const;
186 
187     // Processes performance data from the `/proc/[pid]/stat` and `/proc/[pid]/task/[tid]/stat`
188     // files.
189     void processProcessIoPerfDataLocked(const std::unordered_set<std::string>& filterPackages,
190                                         const android::wp<ProcPidStat>& procPidStat,
191                                         ProcessIoPerfData* processIoPerfData);
192 
193     // Top N per-UID stats per category.
194     int mTopNStatsPerCategory;
195 
196     // Top N per-process stats per subcategory.
197     int mTopNStatsPerSubcategory;
198 
199     // Local IPackageInfoResolver instance. Useful to mock in tests.
200     sp<IPackageInfoResolver> mPackageInfoResolver;
201 
202     // Makes sure only one collection is running at any given time.
203     Mutex mMutex;
204 
205     // Info for the boot-time collection event. The cache is persisted until system shutdown/reboot.
206     CollectionInfo mBoottimeCollection GUARDED_BY(mMutex);
207 
208     // Info for the periodic collection event. The cache size is limited by
209     // |ro.carwatchdog.periodic_collection_buffer_size|.
210     CollectionInfo mPeriodicCollection GUARDED_BY(mMutex);
211 
212     // Info for the custom collection event. The info is cleared at the end of every custom
213     // collection.
214     CollectionInfo mCustomCollection GUARDED_BY(mMutex);
215 
216     // Major faults delta from last collection. Useful when calculating the percentage change in
217     // major faults since last collection.
218     uint64_t mLastMajorFaults GUARDED_BY(mMutex);
219 
220     friend class WatchdogPerfService;
221 
222     // For unit tests.
223     friend class internal::IoPerfCollectionPeer;
224     FRIEND_TEST(IoPerfCollectionTest, TestUidIoStatsGreaterThanTopNStatsLimit);
225     FRIEND_TEST(IoPerfCollectionTest, TestUidIOStatsLessThanTopNStatsLimit);
226     FRIEND_TEST(IoPerfCollectionTest, TestProcessSystemIoPerfData);
227     FRIEND_TEST(IoPerfCollectionTest, TestProcPidContentsGreaterThanTopNStatsLimit);
228     FRIEND_TEST(IoPerfCollectionTest, TestProcPidContentsLessThanTopNStatsLimit);
229 };
230 
231 }  // namespace watchdog
232 }  // namespace automotive
233 }  // namespace android
234 
235 #endif  //  CPP_WATCHDOG_SERVER_SRC_IOPERFCOLLECTION_H_
236