Loading libs/graphicsenv/GpuStatsInfo.cpp +3 −0 Original line number Diff line number Diff line Loading @@ -88,6 +88,7 @@ status_t GpuStatsAppInfo::writeToParcel(Parcel* parcel) const { if ((status = parcel->writeBool(cpuVulkanInUse)) != OK) return status; if ((status = parcel->writeBool(falsePrerotation)) != OK) return status; if ((status = parcel->writeBool(gles1InUse)) != OK) return status; if ((status = parcel->writeBool(angleInUse)) != OK) return status; return OK; } Loading @@ -101,6 +102,7 @@ status_t GpuStatsAppInfo::readFromParcel(const Parcel* parcel) { if ((status = parcel->readBool(&cpuVulkanInUse)) != OK) return status; if ((status = parcel->readBool(&falsePrerotation)) != OK) return status; if ((status = parcel->readBool(&gles1InUse)) != OK) return status; if ((status = parcel->readBool(&angleInUse)) != OK) return status; return OK; } Loading @@ -111,6 +113,7 @@ std::string GpuStatsAppInfo::toString() const { StringAppendF(&result, "cpuVulkanInUse = %d\n", cpuVulkanInUse); StringAppendF(&result, "falsePrerotation = %d\n", falsePrerotation); StringAppendF(&result, "gles1InUse = %d\n", gles1InUse); StringAppendF(&result, "angleInUse = %d\n", angleInUse); result.append("glDriverLoadingTime:"); for (int32_t loadingTime : glDriverLoadingTime) { StringAppendF(&result, " %d", loadingTime); Loading libs/graphicsenv/include/graphicsenv/GpuStatsInfo.h +5 −1 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ #pragma once #include <chrono> #include <string> #include <vector> Loading Loading @@ -52,7 +53,7 @@ public: }; /* * class for transporting gpu app stats from GpuService to authorized recipents. * class for transporting gpu app stats from GpuService to authorized recipients. * This class is intended to be a data container. */ class GpuStatsAppInfo : public Parcelable { Loading @@ -72,6 +73,9 @@ public: bool cpuVulkanInUse = false; bool falsePrerotation = false; bool gles1InUse = false; bool angleInUse = false; std::chrono::time_point<std::chrono::system_clock> lastAccessTime; }; /* Loading services/gpuservice/gpustats/GpuStats.cpp +42 −6 Original line number Diff line number Diff line Loading @@ -84,6 +84,38 @@ static void addLoadingTime(GpuStatsInfo::Driver driver, int64_t driverLoadingTim } } void GpuStats::purgeOldDriverStats() { ALOG_ASSERT(mAppStats.size() == MAX_NUM_APP_RECORDS); struct GpuStatsApp { // Key is <app package name>+<driver version code>. const std::string *appStatsKey = nullptr; const std::chrono::time_point<std::chrono::system_clock> *lastAccessTime = nullptr; }; std::vector<GpuStatsApp> gpuStatsApps(MAX_NUM_APP_RECORDS); // Create a list of pointers to package names and their last access times. int index = 0; for (const auto & [appStatsKey, gpuStatsAppInfo] : mAppStats) { GpuStatsApp &gpuStatsApp = gpuStatsApps[index]; gpuStatsApp.appStatsKey = &appStatsKey; gpuStatsApp.lastAccessTime = &gpuStatsAppInfo.lastAccessTime; ++index; } // Sort the list with the oldest access times at the front. std::sort(gpuStatsApps.begin(), gpuStatsApps.end(), [](GpuStatsApp a, GpuStatsApp b) -> bool { return *a.lastAccessTime < *b.lastAccessTime; }); // Remove the oldest packages from mAppStats to make room for new apps. for (int i = 0; i < APP_RECORD_HEADROOM; ++i) { mAppStats.erase(*gpuStatsApps[i].appStatsKey); gpuStatsApps[i].appStatsKey = nullptr; gpuStatsApps[i].lastAccessTime = nullptr; } } void GpuStats::insertDriverStats(const std::string& driverPackageName, const std::string& driverVersionName, uint64_t driverVersionCode, int64_t driverBuildTime, const std::string& appPackageName, Loading Loading @@ -123,19 +155,22 @@ void GpuStats::insertDriverStats(const std::string& driverPackageName, const std::string appStatsKey = appPackageName + std::to_string(driverVersionCode); if (!mAppStats.count(appStatsKey)) { if (mAppStats.size() >= MAX_NUM_APP_RECORDS) { ALOGV("GpuStatsAppInfo has reached maximum size. Ignore new stats."); return; ALOGV("GpuStatsAppInfo has reached maximum size. Removing old stats to make room."); purgeOldDriverStats(); } GpuStatsAppInfo appInfo; addLoadingTime(driver, driverLoadingTime, &appInfo); appInfo.appPackageName = appPackageName; appInfo.driverVersionCode = driverVersionCode; appInfo.angleInUse = driverPackageName == "angle"; appInfo.lastAccessTime = std::chrono::system_clock::now(); mAppStats.insert({appStatsKey, appInfo}); return; } } else { mAppStats[appStatsKey].angleInUse = driverPackageName == "angle"; addLoadingTime(driver, driverLoadingTime, &mAppStats[appStatsKey]); mAppStats[appStatsKey].lastAccessTime = std::chrono::system_clock::now(); } } void GpuStats::insertTargetStats(const std::string& appPackageName, Loading Loading @@ -311,7 +346,8 @@ AStatsManager_PullAtomCallbackReturn GpuStats::pullAppInfoAtom(AStatsEventList* angleDriverBytes.length()), ele.second.cpuVulkanInUse, ele.second.falsePrerotation, ele.second.gles1InUse); ele.second.gles1InUse, ele.second.angleInUse); } } Loading services/gpuservice/gpustats/include/gpustats/GpuStats.h +9 −3 Original line number Diff line number Diff line Loading @@ -46,6 +46,11 @@ public: // This limits the worst case number of loading times tracked. static const size_t MAX_NUM_LOADING_TIMES = 50; // Below limits the memory usage of GpuStats to be less than 10KB. This is // the preferred number for statsd while maintaining nice data quality. static const size_t MAX_NUM_APP_RECORDS = 100; // The number of apps to remove when mAppStats fills up. static const size_t APP_RECORD_HEADROOM = 10; private: // Friend class for testing. Loading @@ -55,6 +60,10 @@ private: static AStatsManager_PullAtomCallbackReturn pullAtomCallback(int32_t atomTag, AStatsEventList* data, void* cookie); // Remove old packages from mAppStats. void purgeOldDriverStats(); // Pull global into into global atom. AStatsManager_PullAtomCallbackReturn pullGlobalInfoAtom(AStatsEventList* data); // Pull app into into app atom. Loading @@ -68,9 +77,6 @@ private: // Registers statsd callbacks if they have not already been registered void registerStatsdCallbacksIfNeeded(); // Below limits the memory usage of GpuStats to be less than 10KB. This is // the preferred number for statsd while maintaining nice data quality. static const size_t MAX_NUM_APP_RECORDS = 100; // GpuStats access should be guarded by mLock. std::mutex mLock; // True if statsd callbacks have been registered. Loading services/gpuservice/tests/unittests/GpuStatsTest.cpp +46 −0 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ #undef LOG_TAG #define LOG_TAG "gpuservice_unittest" #include <unistd.h> #include <cutils/properties.h> #include <gmock/gmock.h> #include <gpustats/GpuStats.h> Loading Loading @@ -221,6 +222,51 @@ TEST_F(GpuStatsTest, canInsertTargetStatsAfterProperSetup) { EXPECT_THAT(inputCommand(InputCommand::DUMP_APP), HasSubstr("gles1InUse = 1")); } // Verify we always have the most recently used apps in mAppStats, even when we fill it. TEST_F(GpuStatsTest, canInsertMoreThanMaxNumAppRecords) { constexpr int kNumExtraApps = 15; static_assert(kNumExtraApps > GpuStats::APP_RECORD_HEADROOM); // Insert stats for GpuStats::MAX_NUM_APP_RECORDS so we fill it up. for (int i = 0; i < GpuStats::MAX_NUM_APP_RECORDS + kNumExtraApps; ++i) { std::stringstream nameStream; nameStream << "testapp" << "_" << i; std::string fullPkgName = nameStream.str(); mGpuStats->insertDriverStats(BUILTIN_DRIVER_PKG_NAME, BUILTIN_DRIVER_VER_NAME, BUILTIN_DRIVER_VER_CODE, BUILTIN_DRIVER_BUILD_TIME, fullPkgName, VULKAN_VERSION, GpuStatsInfo::Driver::GL, true, DRIVER_LOADING_TIME_1); mGpuStats->insertTargetStats(fullPkgName, BUILTIN_DRIVER_VER_CODE, GpuStatsInfo::Stats::CPU_VULKAN_IN_USE, 0); mGpuStats->insertTargetStats(fullPkgName, BUILTIN_DRIVER_VER_CODE, GpuStatsInfo::Stats::FALSE_PREROTATION, 0); mGpuStats->insertTargetStats(fullPkgName, BUILTIN_DRIVER_VER_CODE, GpuStatsInfo::Stats::GLES_1_IN_USE, 0); EXPECT_THAT(inputCommand(InputCommand::DUMP_APP), HasSubstr(fullPkgName.c_str())); EXPECT_THAT(inputCommand(InputCommand::DUMP_APP), HasSubstr("cpuVulkanInUse = 1")); EXPECT_THAT(inputCommand(InputCommand::DUMP_APP), HasSubstr("falsePrerotation = 1")); EXPECT_THAT(inputCommand(InputCommand::DUMP_APP), HasSubstr("gles1InUse = 1")); } // mAppStats purges GpuStats::APP_RECORD_HEADROOM apps removed everytime it's filled up. int numPurges = kNumExtraApps / GpuStats::APP_RECORD_HEADROOM; numPurges += (kNumExtraApps % GpuStats::APP_RECORD_HEADROOM) == 0 ? 0 : 1; // Verify the remaining apps are present. for (int i = numPurges * GpuStats::APP_RECORD_HEADROOM; i < GpuStats::MAX_NUM_APP_RECORDS + kNumExtraApps; ++i) { std::stringstream nameStream; // Add a newline to search for the exact package name. nameStream << "testapp" << "_" << i << "\n"; std::string fullPkgName = nameStream.str(); EXPECT_THAT(inputCommand(InputCommand::DUMP_APP), HasSubstr(fullPkgName.c_str())); } } TEST_F(GpuStatsTest, canDumpAllBeforeClearAll) { mGpuStats->insertDriverStats(BUILTIN_DRIVER_PKG_NAME, BUILTIN_DRIVER_VER_NAME, BUILTIN_DRIVER_VER_CODE, BUILTIN_DRIVER_BUILD_TIME, APP_PKG_NAME_1, Loading Loading
libs/graphicsenv/GpuStatsInfo.cpp +3 −0 Original line number Diff line number Diff line Loading @@ -88,6 +88,7 @@ status_t GpuStatsAppInfo::writeToParcel(Parcel* parcel) const { if ((status = parcel->writeBool(cpuVulkanInUse)) != OK) return status; if ((status = parcel->writeBool(falsePrerotation)) != OK) return status; if ((status = parcel->writeBool(gles1InUse)) != OK) return status; if ((status = parcel->writeBool(angleInUse)) != OK) return status; return OK; } Loading @@ -101,6 +102,7 @@ status_t GpuStatsAppInfo::readFromParcel(const Parcel* parcel) { if ((status = parcel->readBool(&cpuVulkanInUse)) != OK) return status; if ((status = parcel->readBool(&falsePrerotation)) != OK) return status; if ((status = parcel->readBool(&gles1InUse)) != OK) return status; if ((status = parcel->readBool(&angleInUse)) != OK) return status; return OK; } Loading @@ -111,6 +113,7 @@ std::string GpuStatsAppInfo::toString() const { StringAppendF(&result, "cpuVulkanInUse = %d\n", cpuVulkanInUse); StringAppendF(&result, "falsePrerotation = %d\n", falsePrerotation); StringAppendF(&result, "gles1InUse = %d\n", gles1InUse); StringAppendF(&result, "angleInUse = %d\n", angleInUse); result.append("glDriverLoadingTime:"); for (int32_t loadingTime : glDriverLoadingTime) { StringAppendF(&result, " %d", loadingTime); Loading
libs/graphicsenv/include/graphicsenv/GpuStatsInfo.h +5 −1 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ #pragma once #include <chrono> #include <string> #include <vector> Loading Loading @@ -52,7 +53,7 @@ public: }; /* * class for transporting gpu app stats from GpuService to authorized recipents. * class for transporting gpu app stats from GpuService to authorized recipients. * This class is intended to be a data container. */ class GpuStatsAppInfo : public Parcelable { Loading @@ -72,6 +73,9 @@ public: bool cpuVulkanInUse = false; bool falsePrerotation = false; bool gles1InUse = false; bool angleInUse = false; std::chrono::time_point<std::chrono::system_clock> lastAccessTime; }; /* Loading
services/gpuservice/gpustats/GpuStats.cpp +42 −6 Original line number Diff line number Diff line Loading @@ -84,6 +84,38 @@ static void addLoadingTime(GpuStatsInfo::Driver driver, int64_t driverLoadingTim } } void GpuStats::purgeOldDriverStats() { ALOG_ASSERT(mAppStats.size() == MAX_NUM_APP_RECORDS); struct GpuStatsApp { // Key is <app package name>+<driver version code>. const std::string *appStatsKey = nullptr; const std::chrono::time_point<std::chrono::system_clock> *lastAccessTime = nullptr; }; std::vector<GpuStatsApp> gpuStatsApps(MAX_NUM_APP_RECORDS); // Create a list of pointers to package names and their last access times. int index = 0; for (const auto & [appStatsKey, gpuStatsAppInfo] : mAppStats) { GpuStatsApp &gpuStatsApp = gpuStatsApps[index]; gpuStatsApp.appStatsKey = &appStatsKey; gpuStatsApp.lastAccessTime = &gpuStatsAppInfo.lastAccessTime; ++index; } // Sort the list with the oldest access times at the front. std::sort(gpuStatsApps.begin(), gpuStatsApps.end(), [](GpuStatsApp a, GpuStatsApp b) -> bool { return *a.lastAccessTime < *b.lastAccessTime; }); // Remove the oldest packages from mAppStats to make room for new apps. for (int i = 0; i < APP_RECORD_HEADROOM; ++i) { mAppStats.erase(*gpuStatsApps[i].appStatsKey); gpuStatsApps[i].appStatsKey = nullptr; gpuStatsApps[i].lastAccessTime = nullptr; } } void GpuStats::insertDriverStats(const std::string& driverPackageName, const std::string& driverVersionName, uint64_t driverVersionCode, int64_t driverBuildTime, const std::string& appPackageName, Loading Loading @@ -123,19 +155,22 @@ void GpuStats::insertDriverStats(const std::string& driverPackageName, const std::string appStatsKey = appPackageName + std::to_string(driverVersionCode); if (!mAppStats.count(appStatsKey)) { if (mAppStats.size() >= MAX_NUM_APP_RECORDS) { ALOGV("GpuStatsAppInfo has reached maximum size. Ignore new stats."); return; ALOGV("GpuStatsAppInfo has reached maximum size. Removing old stats to make room."); purgeOldDriverStats(); } GpuStatsAppInfo appInfo; addLoadingTime(driver, driverLoadingTime, &appInfo); appInfo.appPackageName = appPackageName; appInfo.driverVersionCode = driverVersionCode; appInfo.angleInUse = driverPackageName == "angle"; appInfo.lastAccessTime = std::chrono::system_clock::now(); mAppStats.insert({appStatsKey, appInfo}); return; } } else { mAppStats[appStatsKey].angleInUse = driverPackageName == "angle"; addLoadingTime(driver, driverLoadingTime, &mAppStats[appStatsKey]); mAppStats[appStatsKey].lastAccessTime = std::chrono::system_clock::now(); } } void GpuStats::insertTargetStats(const std::string& appPackageName, Loading Loading @@ -311,7 +346,8 @@ AStatsManager_PullAtomCallbackReturn GpuStats::pullAppInfoAtom(AStatsEventList* angleDriverBytes.length()), ele.second.cpuVulkanInUse, ele.second.falsePrerotation, ele.second.gles1InUse); ele.second.gles1InUse, ele.second.angleInUse); } } Loading
services/gpuservice/gpustats/include/gpustats/GpuStats.h +9 −3 Original line number Diff line number Diff line Loading @@ -46,6 +46,11 @@ public: // This limits the worst case number of loading times tracked. static const size_t MAX_NUM_LOADING_TIMES = 50; // Below limits the memory usage of GpuStats to be less than 10KB. This is // the preferred number for statsd while maintaining nice data quality. static const size_t MAX_NUM_APP_RECORDS = 100; // The number of apps to remove when mAppStats fills up. static const size_t APP_RECORD_HEADROOM = 10; private: // Friend class for testing. Loading @@ -55,6 +60,10 @@ private: static AStatsManager_PullAtomCallbackReturn pullAtomCallback(int32_t atomTag, AStatsEventList* data, void* cookie); // Remove old packages from mAppStats. void purgeOldDriverStats(); // Pull global into into global atom. AStatsManager_PullAtomCallbackReturn pullGlobalInfoAtom(AStatsEventList* data); // Pull app into into app atom. Loading @@ -68,9 +77,6 @@ private: // Registers statsd callbacks if they have not already been registered void registerStatsdCallbacksIfNeeded(); // Below limits the memory usage of GpuStats to be less than 10KB. This is // the preferred number for statsd while maintaining nice data quality. static const size_t MAX_NUM_APP_RECORDS = 100; // GpuStats access should be guarded by mLock. std::mutex mLock; // True if statsd callbacks have been registered. Loading
services/gpuservice/tests/unittests/GpuStatsTest.cpp +46 −0 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ #undef LOG_TAG #define LOG_TAG "gpuservice_unittest" #include <unistd.h> #include <cutils/properties.h> #include <gmock/gmock.h> #include <gpustats/GpuStats.h> Loading Loading @@ -221,6 +222,51 @@ TEST_F(GpuStatsTest, canInsertTargetStatsAfterProperSetup) { EXPECT_THAT(inputCommand(InputCommand::DUMP_APP), HasSubstr("gles1InUse = 1")); } // Verify we always have the most recently used apps in mAppStats, even when we fill it. TEST_F(GpuStatsTest, canInsertMoreThanMaxNumAppRecords) { constexpr int kNumExtraApps = 15; static_assert(kNumExtraApps > GpuStats::APP_RECORD_HEADROOM); // Insert stats for GpuStats::MAX_NUM_APP_RECORDS so we fill it up. for (int i = 0; i < GpuStats::MAX_NUM_APP_RECORDS + kNumExtraApps; ++i) { std::stringstream nameStream; nameStream << "testapp" << "_" << i; std::string fullPkgName = nameStream.str(); mGpuStats->insertDriverStats(BUILTIN_DRIVER_PKG_NAME, BUILTIN_DRIVER_VER_NAME, BUILTIN_DRIVER_VER_CODE, BUILTIN_DRIVER_BUILD_TIME, fullPkgName, VULKAN_VERSION, GpuStatsInfo::Driver::GL, true, DRIVER_LOADING_TIME_1); mGpuStats->insertTargetStats(fullPkgName, BUILTIN_DRIVER_VER_CODE, GpuStatsInfo::Stats::CPU_VULKAN_IN_USE, 0); mGpuStats->insertTargetStats(fullPkgName, BUILTIN_DRIVER_VER_CODE, GpuStatsInfo::Stats::FALSE_PREROTATION, 0); mGpuStats->insertTargetStats(fullPkgName, BUILTIN_DRIVER_VER_CODE, GpuStatsInfo::Stats::GLES_1_IN_USE, 0); EXPECT_THAT(inputCommand(InputCommand::DUMP_APP), HasSubstr(fullPkgName.c_str())); EXPECT_THAT(inputCommand(InputCommand::DUMP_APP), HasSubstr("cpuVulkanInUse = 1")); EXPECT_THAT(inputCommand(InputCommand::DUMP_APP), HasSubstr("falsePrerotation = 1")); EXPECT_THAT(inputCommand(InputCommand::DUMP_APP), HasSubstr("gles1InUse = 1")); } // mAppStats purges GpuStats::APP_RECORD_HEADROOM apps removed everytime it's filled up. int numPurges = kNumExtraApps / GpuStats::APP_RECORD_HEADROOM; numPurges += (kNumExtraApps % GpuStats::APP_RECORD_HEADROOM) == 0 ? 0 : 1; // Verify the remaining apps are present. for (int i = numPurges * GpuStats::APP_RECORD_HEADROOM; i < GpuStats::MAX_NUM_APP_RECORDS + kNumExtraApps; ++i) { std::stringstream nameStream; // Add a newline to search for the exact package name. nameStream << "testapp" << "_" << i << "\n"; std::string fullPkgName = nameStream.str(); EXPECT_THAT(inputCommand(InputCommand::DUMP_APP), HasSubstr(fullPkgName.c_str())); } } TEST_F(GpuStatsTest, canDumpAllBeforeClearAll) { mGpuStats->insertDriverStats(BUILTIN_DRIVER_PKG_NAME, BUILTIN_DRIVER_VER_NAME, BUILTIN_DRIVER_VER_CODE, BUILTIN_DRIVER_BUILD_TIME, APP_PKG_NAME_1, Loading