/* * Created by Brett on 23/12/22. * Licensed under GNU General Public License V3.0 * See LICENSE file for license detail */ #include #include #include #include #include #include #include #include namespace blt::profiling { // TODO: a better way std::mutex profileLock{}; std::unordered_map profiles; void startInterval(const std::string& profileName, const std::string& intervalName) { std::scoped_lock lock(profileLock); CaptureInterval interval{}; interval.start = System::getCurrentTimeNanoseconds(); profiles[profileName].intervals[intervalName] = interval; } void endInterval(const std::string& profileName, const std::string& intervalName) { std::scoped_lock lock(profileLock); profiles[profileName].intervals[intervalName].end = System::getCurrentTimeNanoseconds(); } void point(const std::string& profileName, const std::string& pointName) { std::scoped_lock lock(profileLock); CapturePoint point{}; point.point = System::getCurrentTimeNanoseconds(); point.name = pointName; profiles[profileName].points.push(point); } CaptureInterval getInterval(const std::string& profileName, const std::string& intervalName) { return profiles[profileName].intervals[intervalName]; } Profile getProfile(const std::string& profileName) { return profiles[profileName]; } inline void print(const std::vector& lines, int level) { if (level < 0) { for (const auto& line : lines) std::cout << line; } else { auto& logger = logging::loggerLevelDecode[level]; for (const auto& line : lines) logger << line; } } void printProfile(const std::string& profileName, int loggingLevel) { string::TableFormatter formatter {profileName}; formatter.addColumn({"Interval"}); formatter.addColumn({"Time (ns)"}); formatter.addColumn({"Time (ms)"}); const auto& profile = profiles[profileName]; const auto& intervals = profile.intervals; const auto& points = profile.points; for (const auto& interval : intervals) { const auto difference = interval.second.end - interval.second.start; formatter.addRow({interval.first, std::to_string(difference), std::to_string((double)difference/1000000.0)}); } std::vector updatedLines; const auto& lines = formatter.createTable(true, true); for (const auto& line : lines) updatedLines.emplace_back(line + "\n"); print(updatedLines, loggingLevel); } struct timeOrderContainer { long difference; std::string name; timeOrderContainer(long difference, std::string name): difference(difference), name(std::move(name)) {} }; inline bool timeCompare(const timeOrderContainer& container1, const timeOrderContainer& container2) { return container1.difference < container2.difference; } void printOrderedProfile(const std::string& profileName, int loggingLevel) { const auto& profile = profiles[profileName]; const auto& intervals = profile.intervals; const auto& points = profile.points; std::vector unorderedIntervalVector; for (const auto& interval : intervals) { const auto difference = interval.second.end - interval.second.start; unorderedIntervalVector.emplace_back(difference, interval.first); } std::sort(unorderedIntervalVector.begin(), unorderedIntervalVector.end(), timeCompare); string::TableFormatter formatter {profileName}; formatter.addColumn({"Order"}); formatter.addColumn({"Interval"}); formatter.addColumn({"Time (ns)"}); formatter.addColumn({"Time (ms)"}); int index = 1; for (const auto& interval : unorderedIntervalVector) { formatter.addRow({std::to_string(index++), interval.name, std::to_string(interval.difference), std::to_string(interval.difference / 1000000.0)}); } std::vector updatedLines; const auto& lines = formatter.createTable(true, true); for (const auto& line : lines) updatedLines.emplace_back(line + "\n"); print(updatedLines, loggingLevel); } void discardProfiles() { profiles = {}; } void discardIntervals(const std::string& profileName) { profiles[profileName].intervals = {}; } void discardPoints(const std::string& profileName) { profiles[profileName].points = {}; } }