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