From 9adabd6cfa4b151cc404302a02c296ddf686ffa2 Mon Sep 17 00:00:00 2001 From: Junyi Ye <294572668@qq.com> Date: Mon, 22 Apr 2024 18:42:02 +0800 Subject: [PATCH 1/2] Optimize uncore event query. --- pmu/pmu.cpp | 18 ++-- pmu/pmu_event_list.cpp | 185 +++++++++++++++++++++++++++++++++++++++++ pmu/pmu_list.cpp | 39 ++++++++- pmu/pmu_list.h | 2 +- 4 files changed, 232 insertions(+), 12 deletions(-) create mode 100644 pmu/pmu_event_list.cpp diff --git a/pmu/pmu.cpp b/pmu/pmu.cpp index 2f05b57..56b4618 100644 --- a/pmu/pmu.cpp +++ b/pmu/pmu.cpp @@ -35,7 +35,7 @@ using namespace std; static unordered_map runningStatus; static SafeHandler pdMutex; -static const int NINE = 9; +static pair uncoreEventPair; struct PmuTaskAttr* AssignPmuTaskParam(PmuTaskType collectType, struct PmuAttr *attr); @@ -127,14 +127,11 @@ void AppendChildEvents(char* evt, unordered_map& eventSplitMap) auto findSlash = strName.find('/'); string devName = strName.substr(0, findSlash); string evtName = strName.substr(devName.size(), strName.size() - devName.size() + 1); - for (int i = 0; i <= NINE; i++) { - string typePath = "/sys/devices/"; - string childName = devName; - typePath += devName + to_string(i) + "/type"; - string realPath = GetRealPath(typePath); - childName += to_string(i) + evtName; - if (IsValidPath(realPath)) { - eventSplitMap.emplace(childName, evt); + auto numEvt = uncoreEventPair.first; + auto uncoreEventList = uncoreEventPair.second; + for (int i = 0; i < numEvt; ++i) { + if (std::strncmp(uncoreEventList[i], devName.c_str(), devName.length()) == 0) { + eventSplitMap.emplace(uncoreEventList[i], evt); } } } @@ -144,6 +141,9 @@ static void SplitUncoreEvent(struct PmuAttr *attr, unordered_map char** evtList = attr->evtList; unsigned size = attr->numEvt; int newSize = 0; + unsigned numEvt; + auto eventList = PmuEventList(UNCORE_EVENT, &numEvt); + uncoreEventPair = make_pair(numEvt, eventList); for (int i = 0; i < size; ++i) { char* evt = evtList[i]; char* slashPos = std::strchr(evt, '/'); diff --git a/pmu/pmu_event_list.cpp b/pmu/pmu_event_list.cpp new file mode 100644 index 0000000..7088388 --- /dev/null +++ b/pmu/pmu_event_list.cpp @@ -0,0 +1,185 @@ +/** + * @copyright Copyright (c) Huawei Technologies Co., Ltd. 2023-2023. All rights reserved. + * @brief + * @version 24.0 + * @date 2024-04-18 + */ +#include +#include +#include +#include +#include +#include +#include +#include "core.h" +#include "pcerr.h" +#include "pmu.h" + +using namespace pcerr; +using namespace std; +using EvtQueryer = function; + +static const string SLASH = "/"; +static const string COLON = ":"; +static const string UNCORE_PREFIX = "hisi"; +static const string SYS_DEVICES = "/sys/devices/"; +static const string EVENT_DIR = "/events/"; +static const string TRACE_FOLDER = "/sys/kernel/tracing/events/"; + +static std::mutex pmuEventListMtx; + +static vector uncoreEventList; +static vector traceEventList; + +static void GetEventName(const string& devName, vector& eventList) +{ + DIR* dir; + struct dirent* entry; + auto path = SYS_DEVICES + devName + EVENT_DIR; + if ((dir = opendir(path.c_str())) == nullptr) { + New(LIBPERF_ERR_FOLDER_PATH_INACCESSIBLE, "Could not open \"/sys/devices/\""); + return; + } + while ((entry = readdir(dir)) != nullptr) { + if (entry->d_type != DT_REG) { // Check if it is a regular file + continue; + } + string fileName(entry->d_name); + auto eventName = devName; + eventName += SLASH + fileName; + eventName += SLASH; + char* eventNameCopy = new char[eventName.length() + 1]; + strcpy(eventNameCopy, eventName.c_str()); + eventList.push_back(eventNameCopy); + } + closedir(dir); +} + +static void GetTraceSubFolder(const string& devName, vector& eventList) +{ + DIR* dir; + struct dirent* entry; + auto path = TRACE_FOLDER + devName; + if ((dir = opendir(path.c_str())) == nullptr) { + New(LIBPERF_ERR_FOLDER_PATH_INACCESSIBLE, "Could not open " + path); + return; + } + while ((entry = readdir(dir)) != nullptr) { + if (entry->d_type != DT_DIR) { // Check if it is a regular folder + continue; + } + string folderName(entry->d_name); + if (folderName.find('.') == string::npos) { + auto eventName = devName; + eventName += COLON + folderName; + char* eventNameCopy = new char[eventName.length() + 1]; + strcpy(eventNameCopy, eventName.c_str()); + eventList.push_back(eventNameCopy); + } + } + closedir(dir); +} + +const char** QueryCoreEvent(unsigned *numEvt) +{ + static vector eventList; + auto coreEventMap = KUNPENG_PMU::CORE_EVENT_MAP.at(GetCpuType()); + for (auto& pair : coreEventMap) { + auto eventName = pair.first; + char* eventNameCopy = new char[eventName.length() + 1]; + strcpy(eventNameCopy, eventName.c_str()); + eventList.push_back(eventNameCopy); + } + *numEvt = eventList.size(); + return eventList.data(); +} + +const char** QueryUncoreEvent(unsigned *numEvt) +{ + DIR* dir; + struct dirent* entry; + dir = opendir(SYS_DEVICES.c_str()); + while ((entry = readdir(dir)) != nullptr) { + if (entry->d_type == DT_DIR) { + string folderName = entry->d_name; + if (folderName.find(UNCORE_PREFIX) == 0) { + string devName(entry->d_name); + GetEventName(devName, uncoreEventList); + } + } + } + closedir(dir); + *numEvt = uncoreEventList.size(); + return uncoreEventList.data(); +} + +const char** QueryTraceEvent(unsigned *numEvt) +{ + DIR* dir; + struct dirent* entry; + dir = opendir(TRACE_FOLDER.c_str()); + while ((entry = readdir(dir)) != nullptr) { + if (entry->d_type == DT_DIR) { + string folderName = entry->d_name; + if (folderName.find('.') == string::npos) { + string devName(entry->d_name); + GetTraceSubFolder(devName, traceEventList); + } + } + } + closedir(dir); + *numEvt = traceEventList.size(); + return traceEventList.data(); +} + +const char** QueryAllEvent(unsigned *numEvt) +{ + unsigned coreNum; + unsigned uncoreNum; + unsigned traceNum; + auto coreList = QueryCoreEvent(&coreNum); + auto uncoreList = QueryUncoreEvent(&uncoreNum); + auto traceList = QueryTraceEvent(&traceNum); + *numEvt = coreNum + uncoreNum + traceNum; + const char** combinedList = new const char* [*numEvt]; + memcpy(combinedList, coreList, coreNum * sizeof(char*)); + memcpy(combinedList + coreNum, uncoreList, uncoreNum * sizeof(char*)); + memcpy(combinedList + coreNum + uncoreNum, traceList, traceNum * sizeof(char*)); + return combinedList; +} + +static const unordered_map QueryMap{ + {PmuEventType::CORE_EVENT, QueryCoreEvent}, + {PmuEventType::UNCORE_EVENT, QueryUncoreEvent}, + {PmuEventType::TRACE_EVENT, QueryTraceEvent}, + {PmuEventType::ALL_EVENT, QueryAllEvent}, +}; + +const char** PmuEventList(enum PmuEventType eventType, unsigned *numEvt) +{ + lock_guard lg(pmuEventListMtx); + const char** eventList; + if (QueryMap.find(eventType) == QueryMap.end()) { + New(LIBPERF_ERR_QUERY_EVENT_TYPE_INVALID, "Event type is invalid."); + return nullptr; + } + try { + eventList = QueryMap.at(eventType)(numEvt); + } catch (...) { + New(LIBPERF_ERR_QUERY_EVENT_LIST_FAILED, "Query event failed."); + return nullptr; + } + New(SUCCESS); + return eventList; +} + +void PmuEventListFree(const char** eventList, unsigned *numEvt) +{ + lock_guard lg(pmuEventListMtx); + for (unsigned i = 0; i < *numEvt; i++) { + delete[] eventList[i]; + } + uncoreEventList.clear(); + traceEventList.clear(); + New(SUCCESS); +} \ No newline at end of file diff --git a/pmu/pmu_list.cpp b/pmu/pmu_list.cpp index 4ac2fa9..95d9760 100644 --- a/pmu/pmu_list.cpp +++ b/pmu/pmu_list.cpp @@ -381,7 +381,34 @@ namespace KUNPENG_PMU { } } - std::vector& PmuList::ExchangeToUserData(const unsigned pd) + void PmuList::AggregateUncoreData(const unsigned pd, const vector& evData, vector& newEvData) + { + // One count for same parent according to parentEventMap. + auto parentMap = parentEventMap.at(pd); + unordered_map dataMap; + for (auto& pmuData : evData) { + auto parentName = parentMap.at(pmuData.evt); + if (strcmp(parentName, pmuData.evt) == 0) { + // event was not split + newEvData.emplace_back(pmuData); + continue; + } + if (dataMap.find(parentName) == dataMap.end()) { + // split uncore event which not recorded in dataMap yet + dataMap[parentName] = pmuData; + dataMap[parentName].evt = parentMap.at(pmuData.evt); + dataMap[parentName].cpu = 0; + dataMap[parentName].cpuTopo = nullptr; + } else { + dataMap.at(parentMap.at(pmuData.evt)).count += pmuData.count; + } + } + for (const auto& pair : dataMap) { + newEvData.emplace_back(pair.second); + } + } + + vector& PmuList::ExchangeToUserData(const unsigned pd) { lock_guard lg(dataListMtx); if (dataList.count(pd) == 0) { @@ -391,7 +418,15 @@ namespace KUNPENG_PMU { auto& evData = dataList[pd]; auto pData = evData.data.data(); if (GetTaskType(pd) == COUNTING) { - auto inserted = userDataList.emplace(pData, move(evData)); + std::vector newPmuData; + AggregateUncoreData(pd, evData.data, newPmuData); + EventData newEvData = { + .pd = pd, + .collectType = COUNTING, + .data = newPmuData, + }; + + auto inserted = userDataList.emplace(newEvData.data.data(), move(newEvData)); dataList.erase(pd); return inserted.first->second.data; } else { diff --git a/pmu/pmu_list.h b/pmu/pmu_list.h index 90f588b..42631b9 100644 --- a/pmu/pmu_list.h +++ b/pmu/pmu_list.h @@ -111,7 +111,7 @@ private: int PrepareProcTopoList(PmuTaskAttr* pmuTaskAttrHead, std::vector& procTopoList) const; int CheckRlimit(const unsigned fdNum); static void AggregateData(const std::vector& evData, std::vector& newEvData); - void AggregateUncoreData(const unsigned pd, const std::vector &evData, std::vector &newEvData); + void PmuList::AggregateUncoreData(const unsigned pd, const vector& evData, vector& newEvData) std::vector& GetPreviousData(const unsigned pd); static std::mutex pmuListMtx; -- Gitee From 14486ff5a2255050c41d1bf25d314adeb52b8e2d Mon Sep 17 00:00:00 2001 From: Junyi Ye <294572668@qq.com> Date: Mon, 22 Apr 2024 18:52:30 +0800 Subject: [PATCH 2/2] Optimize uncore event query. --- pmu/pmu_list.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pmu/pmu_list.h b/pmu/pmu_list.h index 42631b9..90f588b 100644 --- a/pmu/pmu_list.h +++ b/pmu/pmu_list.h @@ -111,7 +111,7 @@ private: int PrepareProcTopoList(PmuTaskAttr* pmuTaskAttrHead, std::vector& procTopoList) const; int CheckRlimit(const unsigned fdNum); static void AggregateData(const std::vector& evData, std::vector& newEvData); - void PmuList::AggregateUncoreData(const unsigned pd, const vector& evData, vector& newEvData) + void AggregateUncoreData(const unsigned pd, const std::vector &evData, std::vector &newEvData); std::vector& GetPreviousData(const unsigned pd); static std::mutex pmuListMtx; -- Gitee