/* * Copyright (C) 2018-2025 Intel Corporation * * SPDX-License-Identifier: MIT * */ #include "shared/source/utilities/perf_profiler.h" #include "shared/source/utilities/stackvec.h" #include #include #include #include #include namespace NEO { std::atomic PerfProfiler::counter(0); thread_local PerfProfiler *gPerfProfiler = nullptr; PerfProfiler *PerfProfiler::objects[PerfProfiler::objectsNumber] = { nullptr, }; PerfProfiler *PerfProfiler::create(bool dumpToFile) { if (gPerfProfiler == nullptr) { int old = counter.fetch_add(1); if (!dumpToFile) { std::unique_ptr logs = std::unique_ptr(new std::stringstream()); std::unique_ptr sysLogs = std::unique_ptr(new std::stringstream()); gPerfProfiler = new PerfProfiler(old, std::move(logs), std::move(sysLogs)); } else { gPerfProfiler = new PerfProfiler(old); } objects[old] = gPerfProfiler; } return gPerfProfiler; } void PerfProfiler::destroyAll() { int count = counter; for (int i = 0; i < count; i++) { if (objects[i] != nullptr) { delete objects[i]; objects[i] = nullptr; } } counter = 0; gPerfProfiler = nullptr; } PerfProfiler::PerfProfiler(int id, std::unique_ptr &&logOut, std::unique_ptr &&sysLogOut) { apiTimer.setFreq(); systemLogs.reserve(20); if (logOut != nullptr) { this->logFile = std::move(logOut); } else { std::stringstream filename; filename << "PerfReport_Thread_" << id << ".xml"; std::unique_ptr logToFile = std::unique_ptr(new std::ofstream()); logToFile->exceptions(std::ios::failbit | std::ios::badbit); logToFile->open(filename.str().c_str(), std::ios::trunc); this->logFile = std::move(logToFile); } *logFile << "" << std::endl; if (sysLogOut != nullptr) { this->sysLogFile = std::move(sysLogOut); } else { std::stringstream filename; filename << "SysPerfReport_Thread_" << id << ".xml"; std::unique_ptr sysLogToFile = std::unique_ptr(new std::ofstream()); sysLogToFile->exceptions(std::ios::failbit | std::ios::badbit); sysLogToFile->open(filename.str().c_str(), std::ios::trunc); this->sysLogFile = std::move(sysLogToFile); } *sysLogFile << "" << std::endl; } PerfProfiler::~PerfProfiler() { *logFile << "" << std::endl; logFile->flush(); *sysLogFile << "" << std::endl; sysLogFile->flush(); gPerfProfiler = nullptr; } void PerfProfiler::readAndVerify(std::istream &stream, const std::string &token) { StackVec buff; buff.resize(token.size()); size_t numRead = static_cast(stream.readsome(&buff[0], token.size())); if ((numRead != token.size()) || (0 != std::strncmp(&buff[0], token.c_str(), token.size()))) { throw std::runtime_error("ReadAndVerify failed"); } } void PerfProfiler::LogBuilder::write(std::ostream &str, long long start, long long end, long long span, unsigned long long totalSystem, const char *function) { str << "\n"; str << "\n"; str << "\n"; } void PerfProfiler::LogBuilder::read(std::istream &str, long long &start, long long &end, long long &span, unsigned long long &totalSystem, std::string &function) { StackVec funcNameBuff; readAndVerify(str, "\n"); readAndVerify(str, "> start; readAndVerify(str, "\" end=\""); str >> end; readAndVerify(str, "\" time=\""); str >> span; readAndVerify(str, "\" api=\""); str >> totalSystem; readAndVerify(str, "\" system=\""); str >> totalSystem; readAndVerify(str, "\" />\n"); readAndVerify(str, "\n"); function.assign(funcNameBuff.begin(), funcNameBuff.end()); } void PerfProfiler::SysLogBuilder::write(std::ostream &str, long long start, unsigned long long time, unsigned int id) { str << "\n"; str << "\n"; str << "\n"; } void PerfProfiler::SysLogBuilder::read(std::istream &str, long long &start, unsigned long long &time, unsigned int &id) { readAndVerify(str, "> id; readAndVerify(str, "\">\n"); readAndVerify(str, "> start; readAndVerify(str, "\" time=\""); str >> time; readAndVerify(str, "\" />\n"); readAndVerify(str, "\n"); } void PerfProfiler::logTimes(long long start, long long end, long long span, unsigned long long totalSystem, const char *function) { std::stringstream str; LogBuilder::write(str, start, end, span, totalSystem, function); *logFile << str.str(); logFile->flush(); auto it = systemLogs.begin(); while (it != systemLogs.end()) { str.str(std::string()); SysLogBuilder::write(str, it->start, it->time, it->id); *sysLogFile << str.str(); it++; } sysLogFile->flush(); } void PerfProfiler::logSysTimes(long long start, unsigned long long time, unsigned int id) { systemLogs.emplace_back(SystemLog{id, start, time}); } } // namespace NEO