• 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 "ProcDiskStatsCollector.h"
21 #include "ProcStatCollector.h"
22 #include "UidStatsCollector.h"
23 #include "WatchdogPerfService.h"
24 
25 #include <android-base/result.h>
26 #include <cutils/multiuser.h>
27 #include <gtest/gtest_prod.h>
28 #include <utils/Errors.h>
29 #include <utils/Mutex.h>
30 #include <utils/RefBase.h>
31 
32 #include <ctime>
33 #include <string>
34 #include <unordered_set>
35 #include <variant>
36 #include <vector>
37 
38 namespace android {
39 namespace automotive {
40 namespace watchdog {
41 
42 // Number of periodic collection records to cache in memory.
43 constexpr int32_t kDefaultPeriodicCollectionBufferSize = 180;
44 constexpr const char kEmptyCollectionMessage[] = "No collection recorded\n";
45 
46 // Forward declaration for testing use only.
47 namespace internal {
48 
49 class IoPerfCollectionPeer;
50 
51 }  // namespace internal
52 
53 // Below structs should be used only by the implementation and unit tests.
54 /**
55  * Struct to represent user package performance stats.
56  */
57 struct UserPackageStats {
58     struct IoStats {
59         int64_t bytes[UID_STATES] = {0};
60         int64_t fsync[UID_STATES] = {0};
61 
totalBytesUserPackageStats::IoStats62         int64_t totalBytes() const {
63             return std::numeric_limits<int64_t>::max() - bytes[UidState::FOREGROUND] >
64                             bytes[UidState::BACKGROUND]
65                     ? bytes[UidState::FOREGROUND] + bytes[UidState::BACKGROUND]
66                     : std::numeric_limits<int64_t>::max();
67         }
68     };
69     struct ProcStats {
70         uint64_t value = 0;
71         struct ProcessValue {
72             std::string comm = "";
73             uint64_t value = 0;
74         };
75         std::vector<ProcessValue> topNProcesses = {};
76     };
77     uid_t uid = 0;
78     std::string genericPackageName = "";
79     std::variant<std::monostate, IoStats, ProcStats> stats;
80     std::string toString(MetricType metricsType, const int64_t totalIoStats[][UID_STATES]) const;
81     std::string toString(int64_t totalValue) const;
82 };
83 
84 /**
85  * User package summary performance stats collected from the `/proc/uid_io/stats`,
86  * `/proc/[pid]/stat`, `/proc/[pid]/task/[tid]/stat`, and /proc/[pid]/status` files.
87  */
88 struct UserPackageSummaryStats {
89     std::vector<UserPackageStats> topNCpuTimes = {};
90     std::vector<UserPackageStats> topNIoReads = {};
91     std::vector<UserPackageStats> topNIoWrites = {};
92     std::vector<UserPackageStats> topNIoBlocked = {};
93     std::vector<UserPackageStats> topNMajorFaults = {};
94     int64_t totalIoStats[METRIC_TYPES][UID_STATES] = {{0}};
95     std::unordered_map<uid_t, uint64_t> taskCountByUid = {};
96     int64_t totalCpuTimeMillis = 0;
97     uint64_t totalMajorFaults = 0;
98     // Percentage of increase/decrease in the major page faults since last collection.
99     double majorFaultsPercentChange = 0.0;
100     std::string toString() const;
101 };
102 
103 // System performance stats collected from the `/proc/stats` file.
104 struct SystemSummaryStats {
105     int64_t cpuIoWaitTimeMillis = 0;
106     int64_t cpuIdleTimeMillis = 0;
107     int64_t totalCpuTimeMillis = 0;
108     uint64_t contextSwitchesCount = 0;
109     uint32_t ioBlockedProcessCount = 0;
110     uint32_t totalProcessCount = 0;
111     std::string toString() const;
112 };
113 
114 // Performance record collected during a sampling/collection period.
115 struct PerfStatsRecord {
116     time_t time;  // Collection time.
117     SystemSummaryStats systemSummaryStats;
118     UserPackageSummaryStats userPackageSummaryStats;
119     std::string toString() const;
120 };
121 
122 // Group of performance records collected for a collection event.
123 struct CollectionInfo {
124     size_t maxCacheSize = 0;               // Maximum cache size for the collection.
125     std::vector<PerfStatsRecord> records;  // Cache of collected performance records.
126     std::string toString() const;
127 };
128 
129 // Group of performance records collected for a user switch collection event.
130 struct UserSwitchCollectionInfo : CollectionInfo {
131     userid_t from = 0;
132     userid_t to = 0;
133 };
134 
135 // IoPerfCollection implements the I/O performance data collection module.
136 class IoPerfCollection final : public DataProcessorInterface {
137 public:
IoPerfCollection()138     IoPerfCollection() :
139           mTopNStatsPerCategory(0),
140           mTopNStatsPerSubcategory(0),
141           mMaxUserSwitchEvents(0),
142           mBoottimeCollection({}),
143           mPeriodicCollection({}),
144           mUserSwitchCollections({}),
145           mWakeUpCollection({}),
146           mCustomCollection({}),
147           mLastMajorFaults(0) {}
148 
~IoPerfCollection()149     ~IoPerfCollection() { terminate(); }
150 
name()151     std::string name() const override { return "IoPerfCollection"; }
152 
153     // Implements DataProcessorInterface.
154     android::base::Result<void> onSystemStartup() override;
155 
156     android::base::Result<void> onBoottimeCollection(
157             time_t time, const android::wp<UidStatsCollectorInterface>& uidStatsCollector,
158             const android::wp<ProcStatCollectorInterface>& procStatCollector) override;
159 
160     android::base::Result<void> onWakeUpCollection(
161             time_t time, const android::wp<UidStatsCollectorInterface>& uidStatsCollector,
162             const android::wp<ProcStatCollectorInterface>& procStatCollector) override;
163 
164     android::base::Result<void> onPeriodicCollection(
165             time_t time, SystemState systemState,
166             const android::wp<UidStatsCollectorInterface>& uidStatsCollector,
167             const android::wp<ProcStatCollectorInterface>& procStatCollector) override;
168 
169     android::base::Result<void> onUserSwitchCollection(
170             time_t time, userid_t from, userid_t to,
171             const android::wp<UidStatsCollectorInterface>& uidStatsCollector,
172             const android::wp<ProcStatCollectorInterface>& procStatCollector) override;
173 
174     android::base::Result<void> onCustomCollection(
175             time_t time, SystemState systemState,
176             const std::unordered_set<std::string>& filterPackages,
177             const android::wp<UidStatsCollectorInterface>& uidStatsCollector,
178             const android::wp<ProcStatCollectorInterface>& procStatCollector) override;
179 
onPeriodicMonitor(time_t time,const android::wp<ProcDiskStatsCollectorInterface> & procDiskStatsCollector,const std::function<void ()> & alertHandler)180     android::base::Result<void> onPeriodicMonitor(
181             [[maybe_unused]] time_t time,
182             [[maybe_unused]] const android::wp<ProcDiskStatsCollectorInterface>&
183                     procDiskStatsCollector,
184             [[maybe_unused]] const std::function<void()>& alertHandler) override {
185         // No monitoring done here as this DataProcessor only collects I/O performance records.
186         return {};
187     }
188 
189     android::base::Result<void> onDump(int fd) const override;
190 
191     android::base::Result<void> onCustomCollectionDump(int fd) override;
192 
193 protected:
194     android::base::Result<void> init();
195 
196     // Clears in-memory cache.
197     void terminate();
198 
199 private:
200     // Processes the collected data.
201     android::base::Result<void> processLocked(
202             time_t time, const std::unordered_set<std::string>& filterPackages,
203             const android::sp<UidStatsCollectorInterface>& uidStatsCollector,
204             const android::sp<ProcStatCollectorInterface>& procStatCollector,
205             CollectionInfo* collectionInfo);
206 
207     // Processes per-UID performance data.
208     void processUidStatsLocked(const std::unordered_set<std::string>& filterPackages,
209                                const android::sp<UidStatsCollectorInterface>& uidStatsCollector,
210                                UserPackageSummaryStats* userPackageSummaryStats);
211 
212     // Processes system performance data from the `/proc/stats` file.
213     void processProcStatLocked(const android::sp<ProcStatCollectorInterface>& procStatCollector,
214                                SystemSummaryStats* systemSummaryStats) const;
215 
216     // Dump the user switch collection
217     android::base::Result<void> onUserSwitchCollectionDump(int fd) const;
218 
219     // Top N per-UID stats per category.
220     int mTopNStatsPerCategory;
221 
222     // Top N per-process stats per subcategory.
223     int mTopNStatsPerSubcategory;
224 
225     // Max amount of user switch events cached in |mUserSwitchCollections|.
226     size_t mMaxUserSwitchEvents;
227 
228     // Makes sure only one collection is running at any given time.
229     mutable Mutex mMutex;
230 
231     // Info for the boot-time collection event. The cache is persisted until system shutdown/reboot
232     // or a wake-up collection occurs.
233     CollectionInfo mBoottimeCollection GUARDED_BY(mMutex);
234 
235     // Info for the periodic collection event. The cache size is limited by
236     // |ro.carwatchdog.periodic_collection_buffer_size|.
237     CollectionInfo mPeriodicCollection GUARDED_BY(mMutex);
238 
239     // Cache for user switch collection events. Events are cached from oldest to newest.
240     std::vector<UserSwitchCollectionInfo> mUserSwitchCollections GUARDED_BY(mMutex);
241 
242     // Info for the wake-up collection event. Only the latest wake-up collection is cached.
243     CollectionInfo mWakeUpCollection GUARDED_BY(mMutex);
244 
245     // Info for the custom collection event. The info is cleared at the end of every custom
246     // collection.
247     CollectionInfo mCustomCollection GUARDED_BY(mMutex);
248 
249     // Major faults delta from last collection. Useful when calculating the percentage change in
250     // major faults since last collection.
251     uint64_t mLastMajorFaults GUARDED_BY(mMutex);
252 
253     friend class WatchdogPerfService;
254 
255     // For unit tests.
256     friend class internal::IoPerfCollectionPeer;
257 };
258 
259 }  // namespace watchdog
260 }  // namespace automotive
261 }  // namespace android
262 
263 #endif  //  CPP_WATCHDOG_SERVER_SRC_IOPERFCOLLECTION_H_
264