diff --git a/CMakeLists.txt b/CMakeLists.txt index 000fe07..834ce92 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,7 +9,7 @@ option(BUILD_PROFILING "Build the BLT profiler extension" ON) option(BUILD_NBT "Build the BLT NBT + eNBT extension" ON) option(BUILD_TESTS "Build the BLT test set" OFF) -if(${BUILD_STD}) +if(${BUILD_STD} OR ${BUILD_PROFILING}) file(GLOB_RECURSE STD_FILES "${CMAKE_CURRENT_SOURCE_DIR}/src/blt/std/*.cpp") else() set(STD_FILES "") diff --git a/include/blt/profiling/profiler.h b/include/blt/profiling/profiler.h index def2bbd..f0066bc 100644 --- a/include/blt/profiling/profiler.h +++ b/include/blt/profiling/profiler.h @@ -39,8 +39,8 @@ namespace blt::profiling { CaptureInterval getInterval(const std::string& profileName, const std::string& intervalName); Profile getProfile(const std::string& profileName); - void printProfile(const std::string& profileName, int loggingLevel); - void printOrderedProfile(const std::string& profileName, int loggingLevel); + void printProfile(const std::string& profileName, int loggingLevel = -1); + void printOrderedProfile(const std::string& profileName, int loggingLevel = -1); void discardProfiles(); void discardIntervals(const std::string& profileName); @@ -53,36 +53,12 @@ namespace blt::profiling { #define BLT_START_INTERVAL(profileName, intervalName) #define BLT_END_INTERVAL(profileName, intervalName) #define BLT_POINT(profileName, pointName) - #define BLT_PRINT_PROFILE(profileName) - #define BLT_PRINT_ORDERED(profileName) - - #define BLT_PRINT_PROFILE_TRACE(profileName) - #define BLT_PRINT_ORDERED_TRACE(profileName) - - #define BLT_PRINT_PROFILE_DEBUG(profileName) - #define BLT_PRINT_ORDERED_DEBUG(profileName) - - #define BLT_PRINT_PROFILE_INFO(profileName) - #define BLT_PRINT_ORDERED_INFO(profileName) - - #define BLT_PRINT_PROFILE_WARN(profileName) - #define BLT_PRINT_ORDERED_WARN(profileName) + #define BLT_PRINT_PROFILE(profileName, ...) + #define BLT_PRINT_ORDERED(profileName, ...) #else #define BLT_START_INTERVAL(profileName, intervalName) blt::profiling::startInterval(profileName, intervalName); #define BLT_END_INTERVAL(profileName, intervalName) blt::profiling::endInterval(profileName, intervalName); #define BLT_POINT(profileName, pointName) blt::profiling::point(profileName, pointName); - #define BLT_PRINT_PROFILE(profileName) blt::profiling::printProfile(profileName, -1); - #define BLT_PRINT_ORDERED(profileName) blt::profiling::printOrderedProfile(profileName, -1); - - #define BLT_PRINT_PROFILE_TRACE(profileName) blt::profiling::printProfile(profileName, 0); - #define BLT_PRINT_ORDERED_TRACE(profileName) blt::profiling::printOrderedProfile(profileName, 0); - - #define BLT_PRINT_PROFILE_DEBUG(profileName) blt::profiling::printProfile(profileName, 1); - #define BLT_PRINT_ORDERED_DEBUG(profileName) blt::profiling::printOrderedProfile(profileName, 1); - - #define BLT_PRINT_PROFILE_INFO(profileName) blt::profiling::printProfile(profileName, 2); - #define BLT_PRINT_ORDERED_INFO(profileName) blt::profiling::printOrderedProfile(profileName, 2); - - #define BLT_PRINT_PROFILE_WARN(profileName) blt::profiling::printProfile(profileName, 3); - #define BLT_PRINT_ORDERED_WARN(profileName) blt::profiling::printOrderedProfile(profileName, 3); + #define BLT_PRINT_PROFILE(profileName, ...) blt::profiling::printProfile(profileName, ##__VA_ARGS__); + #define BLT_PRINT_ORDERED(profileName, ...) blt::profiling::printOrderedProfile(profileName, ##__VA_ARGS__); #endif \ No newline at end of file diff --git a/include/blt/std/string.h b/include/blt/std/string.h index 0ebff9e..3d57408 100644 --- a/include/blt/std/string.h +++ b/include/blt/std/string.h @@ -12,9 +12,41 @@ #include #include #include +#include namespace blt::string { + /** + * Ensure that string str has expected length, pad after the string otherwise. + * @param str string to pad + * @param expectedLength expected length of the string. + * @return a space padded string + */ + static inline std::string postPadWithSpaces(const std::string& str, size_t expectedLength) { + auto currentSize = (int)(str.length() - 1); + if ((int)expectedLength - currentSize <= 0) + return str; + auto paddedString = str; + for (int i = 0; i < expectedLength - currentSize; i++) + paddedString += " "; + return paddedString; + } + + /** + * Ensure that string str has expected length, pad before the string otherwise. + * @param str string to pad + * @param expectedLength expected length of the string. + * @return a space padded string + */ + static inline std::string prePadWithSpaces(const std::string& str, size_t expectedLength) { + auto currentSize = str.length() - 1; + auto paddedString = std::string(); + for (int i = 0; i < expectedLength - currentSize; i++) + paddedString += " "; + paddedString += str; + return paddedString; + } + static inline bool starts_with(const std::string& string, const std::string& search){ if (search.length() > string.length()) return false; diff --git a/src/blt/profiling/profiler.cpp b/src/blt/profiling/profiler.cpp index 55ddeac..f6b5b60 100644 --- a/src/blt/profiling/profiler.cpp +++ b/src/blt/profiling/profiler.cpp @@ -8,7 +8,9 @@ #include #include #include +#include #include +#include namespace blt::profiling { @@ -40,13 +42,111 @@ namespace blt::profiling { 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) { - //auto& out = loggingLevel < 0 ? std::cout : logging::loggerLevelDecode[loggingLevel]; + std::vector lines; + const auto& profile = profiles[profileName]; + const auto& intervals = profile.intervals; + const auto& points = profile.points; + { + std::string profileNameString = "Profile "; + profileNameString += profileName; + profileNameString += " Recorded {\n"; + lines.emplace_back(profileNameString); + + for (const auto& interval : intervals) { + const auto difference = interval.second.end - interval.second.start; + std::string currentIntervalString = "\t"; + currentIntervalString += interval.first; + currentIntervalString += " "; + currentIntervalString += std::to_string(difference); + currentIntervalString += "ns ("; + currentIntervalString += std::to_string((double) difference / 1000000.0); + currentIntervalString += "ms);\n"; + + lines.emplace_back(currentIntervalString); + } + lines.emplace_back("}\n"); + } + print(lines, 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; + } + + inline std::pair longestInterval(const std::vector& intervalDifferences) { + size_t longestName = 0; + size_t longestIntervalTime = 0; + for (const auto& intervalDifference : intervalDifferences) { + longestName = std::max(longestName, intervalDifference.name.length() - 1); + longestIntervalTime = std::max(longestIntervalTime, std::to_string(intervalDifference.difference).length() - 1); + } + return {longestName, longestIntervalTime}; } void printOrderedProfile(const std::string& profileName, int loggingLevel) { - + std::vector lines; + const auto& profile = profiles[profileName]; + const auto& intervals = profile.intervals; + const auto& points = profile.points; + + { + std::string profileNameString = "Profile "; + profileNameString += profileName; + profileNameString += " Recorded {\n"; + lines.emplace_back(profileNameString); + + 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); + + auto longestName = longestInterval(unorderedIntervalVector); + + + int count = 1; + for (const auto& interval : unorderedIntervalVector) { + const auto difference = interval.difference; + std::string currentIntervalString = "\t"; + std::string countStr = std::to_string(count++); + countStr += ". "; + auto countMaxStrSize = std::to_string(unorderedIntervalVector.size() + 1).length() + countStr.length(); + currentIntervalString += blt::string::postPadWithSpaces(countStr, countMaxStrSize); + currentIntervalString += blt::string::postPadWithSpaces(interval.name, longestName.first); + currentIntervalString += "\t"; + currentIntervalString += blt::string::postPadWithSpaces(std::to_string(difference), longestName.second); + currentIntervalString += "ns ("; + currentIntervalString += std::to_string((double) difference / 1000000.0); + currentIntervalString += "ms);\n"; + + lines.emplace_back(currentIntervalString); + } + lines.emplace_back("}\n"); + } + print(lines, loggingLevel); } void discardProfiles() { diff --git a/src/tests/main.cpp b/src/tests/main.cpp index 4d391e7..aef0ffd 100644 --- a/src/tests/main.cpp +++ b/src/tests/main.cpp @@ -5,10 +5,14 @@ #include "blt/profiling/profiler.h" #include "blt/std/logging.h" #include "blt/std/time.h" +#include +#include int main() { binaryTreeTest(); + BLT_START_INTERVAL("Help", "SuperSet"); + BLT_TRACE(10); BLT_TRACE(10.5); @@ -27,5 +31,26 @@ int main() { std::string hello = "superSexyMax"; std::cout << "String starts with: " << blt::string::contains(hello, "superSexyMaxE") << "\n"; + BLT_END_INTERVAL("Help", "SuperSet"); + + BLT_START_INTERVAL("Help", "SecondSet"); + for (int i = 0; i < 1000; i++){ + ;; + } + BLT_END_INTERVAL("Help", "SecondSet"); + BLT_START_INTERVAL("Help", "UnderSet"); + for (int i = 0; i < 1000; i++){ + ;; + } + BLT_END_INTERVAL("Help", "UnderSet"); + + for (int i = 0; i < 15; i++) { + BLT_START_INTERVAL("Help", "UnderSet" + std::to_string(i)); + BLT_END_INTERVAL("Help", "UnderSet" + std::to_string(i)); + } + + BLT_PRINT_PROFILE("Help", blt::logging::LOG_LEVEL::TRACE); + BLT_PRINT_ORDERED("Help", blt::logging::LOG_LEVEL::TRACE); + return 0; } \ No newline at end of file