diff options
| author | 2019-02-24 22:28:08 -0800 | |
|---|---|---|
| committer | 2019-02-26 14:03:42 -0800 | |
| commit | 2d4c18871f2a15e3ab85528a03c4f1871dc96d20 (patch) | |
| tree | 71517643d23162f64d3857a1ec7a36423f5277a6 | |
| parent | bb4eaf622323f861300d5e3091d12113501a9000 (diff) | |
Game Driver: add GpuStats class to process and dump stats
Bug: 123529932
Test: adb shell dumpsys gpu
Change-Id: I2d524b1eecb00be71d344c07e8e18244a44bbcb8
| -rw-r--r-- | libs/graphicsenv/include/graphicsenv/GpuStatsAtoms.h | 42 | ||||
| -rw-r--r-- | services/gpuservice/Android.bp | 1 | ||||
| -rw-r--r-- | services/gpuservice/GpuService.cpp | 36 | ||||
| -rw-r--r-- | services/gpuservice/GpuService.h | 6 | ||||
| -rw-r--r-- | services/gpuservice/gpustats/GpuStats.cpp | 213 | ||||
| -rw-r--r-- | services/gpuservice/gpustats/GpuStats.h | 60 |
6 files changed, 340 insertions, 18 deletions
diff --git a/libs/graphicsenv/include/graphicsenv/GpuStatsAtoms.h b/libs/graphicsenv/include/graphicsenv/GpuStatsAtoms.h new file mode 100644 index 0000000000..f8b0ad72a1 --- /dev/null +++ b/libs/graphicsenv/include/graphicsenv/GpuStatsAtoms.h @@ -0,0 +1,42 @@ +/* + * Copyright 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include <string> +#include <vector> + +namespace android { + +struct GpuStatsGlobalAtom { + std::string driverPackageName = ""; + std::string driverVersionName = ""; + uint64_t driverVersionCode = 0; + int64_t driverBuildTime = 0; + int32_t glLoadingCount = 0; + int32_t glLoadingFailureCount = 0; + int32_t vkLoadingCount = 0; + int32_t vkLoadingFailureCount = 0; +}; + +struct GpuStatsAppAtom { + std::string appPackageName = ""; + uint64_t driverVersionCode = 0; + std::vector<int64_t> glDriverLoadingTime = {}; + std::vector<int64_t> vkDriverLoadingTime = {}; +}; + +} // namespace android diff --git a/services/gpuservice/Android.bp b/services/gpuservice/Android.bp index 2e8571ac4d..dbb6ba6719 100644 --- a/services/gpuservice/Android.bp +++ b/services/gpuservice/Android.bp @@ -2,6 +2,7 @@ filegroup { name: "gpuservice_sources", srcs: [ "GpuService.cpp", + "gpustats/GpuStats.cpp" ], } diff --git a/services/gpuservice/GpuService.cpp b/services/gpuservice/GpuService.cpp index 70dd904541..d7696f9232 100644 --- a/services/gpuservice/GpuService.cpp +++ b/services/gpuservice/GpuService.cpp @@ -29,6 +29,8 @@ #include <vkjson.h> +#include "gpustats/GpuStats.h" + namespace android { using base::StringAppendF; @@ -42,7 +44,7 @@ const String16 sDump("android.permission.DUMP"); const char* const GpuService::SERVICE_NAME = "gpu"; -GpuService::GpuService() = default; +GpuService::GpuService() : mGpuStats(std::make_unique<GpuStats>()){}; void GpuService::setGpuStats(const std::string& driverPackageName, const std::string& driverVersionName, uint64_t driverVersionCode, @@ -51,18 +53,8 @@ void GpuService::setGpuStats(const std::string& driverPackageName, int64_t driverLoadingTime) { ATRACE_CALL(); - std::lock_guard<std::mutex> lock(mStateLock); - ALOGV("Received:\n" - "\tdriverPackageName[%s]\n" - "\tdriverVersionName[%s]\n" - "\tdriverVersionCode[%" PRIu64 "]\n" - "\tdriverBuildTime[%" PRId64 "]\n" - "\tappPackageName[%s]\n" - "\tdriver[%d]\n" - "\tisDriverLoaded[%d]\n" - "\tdriverLoadingTime[%" PRId64 "]", - driverPackageName.c_str(), driverVersionName.c_str(), driverVersionCode, driverBuildTime, - appPackageName.c_str(), static_cast<int32_t>(driver), isDriverLoaded, driverLoadingTime); + mGpuStats->insert(driverPackageName, driverVersionName, driverVersionCode, driverBuildTime, + appPackageName, driver, isDriverLoaded, driverLoadingTime); } status_t GpuService::shellCommand(int /*in*/, int out, int err, std::vector<String16>& args) { @@ -81,7 +73,7 @@ status_t GpuService::shellCommand(int /*in*/, int out, int err, std::vector<Stri return BAD_VALUE; } -status_t GpuService::doDump(int fd, const Vector<String16>& /*args*/, bool /*asProto*/) { +status_t GpuService::doDump(int fd, const Vector<String16>& args, bool /*asProto*/) { std::string result; IPCThreadState* ipc = IPCThreadState::self(); @@ -91,7 +83,21 @@ status_t GpuService::doDump(int fd, const Vector<String16>& /*args*/, bool /*asP if ((uid != AID_SHELL) && !PermissionCache::checkPermission(sDump, pid, uid)) { StringAppendF(&result, "Permission Denial: can't dump gpu from pid=%d, uid=%d\n", pid, uid); } else { - result.append("Hello world from dumpsys gpu.\n"); + bool dumpAll = true; + size_t index = 0; + size_t numArgs = args.size(); + + if (numArgs) { + if ((index < numArgs) && (args[index] == String16("--gpustats"))) { + index++; + mGpuStats->dump(args, &result); + dumpAll = false; + } + } + + if (dumpAll) { + mGpuStats->dump(Vector<String16>(), &result); + } } write(fd, result.c_str(), result.size()); diff --git a/services/gpuservice/GpuService.h b/services/gpuservice/GpuService.h index 7216035cd9..0cf48bb804 100644 --- a/services/gpuservice/GpuService.h +++ b/services/gpuservice/GpuService.h @@ -27,6 +27,8 @@ namespace android { +class GpuStats; + class GpuService : public BnGpuService, public PriorityDumper { public: static const char* const SERVICE_NAME ANDROID_API; @@ -66,9 +68,7 @@ private: /* * Attributes */ - - // GpuStats access must be protected by mStateLock - std::mutex mStateLock; + std::unique_ptr<GpuStats> mGpuStats; }; } // namespace android diff --git a/services/gpuservice/gpustats/GpuStats.cpp b/services/gpuservice/gpustats/GpuStats.cpp new file mode 100644 index 0000000000..43c9492765 --- /dev/null +++ b/services/gpuservice/gpustats/GpuStats.cpp @@ -0,0 +1,213 @@ +/* + * Copyright 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#undef LOG_TAG +#define LOG_TAG "GpuStats" +#define ATRACE_TAG ATRACE_TAG_GRAPHICS + +#include "GpuStats.h" + +#include <android-base/stringprintf.h> +#include <log/log.h> +#include <utils/Trace.h> + +#include <unordered_set> + +namespace android { + +using base::StringAppendF; + +static bool addLoadingCount(GraphicsEnv::Driver driver, bool isDriverLoaded, + GpuStatsGlobalAtom* const outGlobalAtom) { + switch (driver) { + case GraphicsEnv::Driver::GL: + case GraphicsEnv::Driver::GL_UPDATED: + outGlobalAtom->glLoadingCount++; + if (!isDriverLoaded) outGlobalAtom->glLoadingFailureCount++; + break; + case GraphicsEnv::Driver::VULKAN: + case GraphicsEnv::Driver::VULKAN_UPDATED: + outGlobalAtom->vkLoadingCount++; + if (!isDriverLoaded) outGlobalAtom->vkLoadingFailureCount++; + break; + default: + // Currently we don't support GraphicsEnv::Driver::ANGLE because the + // basic driver package info only belongs to system or updated driver. + return false; + } + + return true; +} + +static void addLoadingTime(GraphicsEnv::Driver driver, int64_t driverLoadingTime, + GpuStatsAppAtom* const outAppAtom) { + switch (driver) { + case GraphicsEnv::Driver::GL: + case GraphicsEnv::Driver::GL_UPDATED: + outAppAtom->glDriverLoadingTime.emplace_back(driverLoadingTime); + break; + case GraphicsEnv::Driver::VULKAN: + case GraphicsEnv::Driver::VULKAN_UPDATED: + outAppAtom->vkDriverLoadingTime.emplace_back(driverLoadingTime); + break; + default: + break; + } +} + +void GpuStats::insert(const std::string& driverPackageName, const std::string& driverVersionName, + uint64_t driverVersionCode, int64_t driverBuildTime, + const std::string& appPackageName, GraphicsEnv::Driver driver, + bool isDriverLoaded, int64_t driverLoadingTime) { + ATRACE_CALL(); + + std::lock_guard<std::mutex> lock(mLock); + ALOGV("Received:\n" + "\tdriverPackageName[%s]\n" + "\tdriverVersionName[%s]\n" + "\tdriverVersionCode[%" PRIu64 "]\n" + "\tdriverBuildTime[%" PRId64 "]\n" + "\tappPackageName[%s]\n" + "\tdriver[%d]\n" + "\tisDriverLoaded[%d]\n" + "\tdriverLoadingTime[%" PRId64 "]", + driverPackageName.c_str(), driverVersionName.c_str(), driverVersionCode, driverBuildTime, + appPackageName.c_str(), static_cast<int32_t>(driver), isDriverLoaded, driverLoadingTime); + + if (!mGlobalStats.count(driverVersionCode)) { + GpuStatsGlobalAtom globalAtom; + if (!addLoadingCount(driver, isDriverLoaded, &globalAtom)) { + return; + } + globalAtom.driverPackageName = driverPackageName; + globalAtom.driverVersionName = driverVersionName; + globalAtom.driverVersionCode = driverVersionCode; + globalAtom.driverBuildTime = driverBuildTime; + mGlobalStats.insert({driverVersionCode, globalAtom}); + } else if (!addLoadingCount(driver, isDriverLoaded, &mGlobalStats[driverVersionCode])) { + return; + } + + if (mAppStats.size() >= MAX_NUM_APP_RECORDS) { + ALOGV("GpuStatsAppAtom has reached maximum size. Ignore new stats."); + return; + } + + const std::string appStatsKey = appPackageName + std::to_string(driverVersionCode); + if (!mAppStats.count(appStatsKey)) { + GpuStatsAppAtom appAtom; + addLoadingTime(driver, driverLoadingTime, &appAtom); + appAtom.appPackageName = appPackageName; + appAtom.driverVersionCode = driverVersionCode; + mAppStats.insert({appStatsKey, appAtom}); + return; + } + + addLoadingTime(driver, driverLoadingTime, &mAppStats[appStatsKey]); +} + +void GpuStats::dump(const Vector<String16>& args, std::string* result) { + ATRACE_CALL(); + + if (!result) { + ALOGE("Dump result shouldn't be nullptr."); + return; + } + + std::lock_guard<std::mutex> lock(mLock); + bool dumpAll = true; + + std::unordered_set<std::string> argsSet; + for (size_t i = 0; i < args.size(); i++) { + argsSet.insert(String8(args[i]).c_str()); + } + + const bool dumpGlobal = argsSet.count("--global") != 0; + if (dumpGlobal) { + dumpGlobalLocked(result); + dumpAll = false; + } + + const bool dumpApp = argsSet.count("--app") != 0; + if (dumpApp) { + dumpAppLocked(result); + dumpAll = false; + } + + if (argsSet.count("--clear")) { + bool clearAll = true; + + if (dumpGlobal) { + mGlobalStats.clear(); + clearAll = false; + } + + if (dumpApp) { + mAppStats.clear(); + clearAll = false; + } + + if (clearAll) { + mGlobalStats.clear(); + mAppStats.clear(); + } + + dumpAll = false; + } + + if (dumpAll) { + dumpGlobalLocked(result); + dumpAppLocked(result); + } +} + +void GpuStats::dumpGlobalLocked(std::string* result) { + result->append("GpuStats global:\n"); + + for (const auto& ele : mGlobalStats) { + StringAppendF(result, " driverPackageName = %s\n", ele.second.driverPackageName.c_str()); + StringAppendF(result, " driverVersionName = %s\n", ele.second.driverVersionName.c_str()); + StringAppendF(result, " driverVersionCode = %" PRIu64 "\n", ele.second.driverVersionCode); + StringAppendF(result, " driverBuildTime = %" PRId64 "\n", ele.second.driverBuildTime); + StringAppendF(result, " glLoadingCount = %d\n", ele.second.glLoadingCount); + StringAppendF(result, " glLoadingFailureCount = %d\n", ele.second.glLoadingFailureCount); + StringAppendF(result, " vkLoadingCount = %d\n", ele.second.vkLoadingCount); + StringAppendF(result, " vkLoadingFailureCount = %d\n", ele.second.vkLoadingFailureCount); + result->append("\n"); + } +} + +void GpuStats::dumpAppLocked(std::string* result) { + result->append("GpuStats app:\n"); + + for (const auto& ele : mAppStats) { + StringAppendF(result, " appPackageName = %s\n", ele.second.appPackageName.c_str()); + StringAppendF(result, " driverVersionCode = %" PRIu64 "\n", ele.second.driverVersionCode); + + result->append(" glDriverLoadingTime:"); + for (int32_t loadingTime : ele.second.glDriverLoadingTime) { + StringAppendF(result, " %d", loadingTime); + } + result->append("\n"); + + result->append(" vkDriverLoadingTime:"); + for (int32_t loadingTime : ele.second.vkDriverLoadingTime) { + StringAppendF(result, " %d", loadingTime); + } + result->append("\n\n"); + } +} + +} // namespace android diff --git a/services/gpuservice/gpustats/GpuStats.h b/services/gpuservice/gpustats/GpuStats.h new file mode 100644 index 0000000000..8837c39e8e --- /dev/null +++ b/services/gpuservice/gpustats/GpuStats.h @@ -0,0 +1,60 @@ +/* + * Copyright 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include <mutex> +#include <unordered_map> +#include <vector> + +#include <graphicsenv/GpuStatsAtoms.h> +#include <graphicsenv/GraphicsEnv.h> +#include <utils/String16.h> +#include <utils/Vector.h> + +namespace android { + +class GpuStats { +public: + GpuStats() = default; + ~GpuStats() = default; + + // Insert new gpu stats into global stats and app stats. + void insert(const std::string& driverPackageName, const std::string& driverVersionName, + uint64_t driverVersionCode, int64_t driverBuildTime, + const std::string& appPackageName, GraphicsEnv::Driver driver, bool isDriverLoaded, + int64_t driverLoadingTime); + // dumpsys interface + void dump(const Vector<String16>& args, std::string* result); + +private: + // Dump global stats + void dumpGlobalLocked(std::string* result); + // Dump app stats + void dumpAppLocked(std::string* result); + + // This limits the memory usage of GpuStats to be less than 30KB. This is + // the maximum atom size statsd could afford. + static const size_t MAX_NUM_APP_RECORDS = 300; + // GpuStats access should be guarded by mLock. + std::mutex mLock; + // Key is driver version code. + std::unordered_map<uint64_t, GpuStatsGlobalAtom> mGlobalStats; + // Key is <app package name>+<driver version code>. + std::unordered_map<std::string, GpuStatsAppAtom> mAppStats; +}; + +} // namespace android |