Better profiler

v1
Brett 2023-01-26 00:59:36 -05:00
parent bc4bf76be7
commit e58f20d16e
8 changed files with 153 additions and 1464 deletions

View File

@ -6,6 +6,7 @@ set(CMAKE_CXX_STANDARD 17)
option(BUILD_STD "Build the BLT standard utilities." ON) option(BUILD_STD "Build the BLT standard utilities." ON)
option(BUILD_PROFILING "Build the BLT profiler extension" ON) 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) option(BUILD_TESTS "Build the BLT test set" OFF)
if(${BUILD_STD}) if(${BUILD_STD})
@ -20,6 +21,12 @@ else()
set(PROFILING_FILES "") set(PROFILING_FILES "")
endif() endif()
if(${BUILD_NBT})
file(GLOB_RECURSE NBT_FILES "${CMAKE_CURRENT_SOURCE_DIR}/src/blt/nbt/*.cpp")
else()
set(NBT_FILES "")
endif()
#include parallel hashmaps if the user decided to download the submodule. #include parallel hashmaps if the user decided to download the submodule.
if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/libraries/parallel-hashmap/CMakeLists.txt) if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/libraries/parallel-hashmap/CMakeLists.txt)
set(USE_PHMAPS) set(USE_PHMAPS)
@ -33,8 +40,9 @@ message("Profiler Files ${PROFILING_FILES}")
message("Source: ${CMAKE_SOURCE_DIR}") message("Source: ${CMAKE_SOURCE_DIR}")
message("Current Source: ${CMAKE_CURRENT_SOURCE_DIR}") message("Current Source: ${CMAKE_CURRENT_SOURCE_DIR}")
add_library(BLT ${STD_FILES} ${PROFILING_FILES}) add_library(BLT ${STD_FILES} ${PROFILING_FILES} ${NBT_FILES})
target_include_directories(BLT PUBLIC include/) target_include_directories(BLT PUBLIC include/)
if(${USE_PHMAPS}) if(${USE_PHMAPS})
target_link_libraries(BLT phmap) target_link_libraries(BLT phmap)
endif() endif()

View File

@ -32,6 +32,9 @@ BLT_TESTS_IS_TOP_LEVEL:STATIC=ON
//Value Computed by CMake //Value Computed by CMake
BLT_TESTS_SOURCE_DIR:STATIC=/home/brett/Documents/code/c++/BLT BLT_TESTS_SOURCE_DIR:STATIC=/home/brett/Documents/code/c++/BLT
//Build the BLT NBT + eNBT extension
BUILD_NBT:BOOL=ON
//Build the BLT profiler extension //Build the BLT profiler extension
BUILD_PROFILING:BOOL=ON BUILD_PROFILING:BOOL=ON

View File

@ -8,17 +8,17 @@
#define BLT_PROFILER_H #define BLT_PROFILER_H
#include <string> #include <string>
#include <string_view>
#include <mutex>
#include <vector>
#include <blt/std/time.h>
#include <blt/std/queue.h> #include <blt/std/queue.h>
#include <iostream> #include <unordered_map>
namespace blt { /**
* Defines several disableable macros (#define BLT_DISABLE_PROFILING). If you do not use these macros profiling will not be disableable
*/
namespace blt::profiling {
struct CapturePoint { struct CapturePoint {
std::string_view name; std::string name;
long point; long point {};
}; };
struct CaptureInterval { struct CaptureInterval {
@ -26,70 +26,63 @@ namespace blt {
long end; long end;
}; };
/** struct Profile {
* @tparam HASHMAP_TYPE std::unordered_map<std::string, CaptureInterval> intervals;
*/ blt::flat_queue<CapturePoint> points;
template <template<typename, typename> class HASHMAP_TYPE>
class profile {
private:
// profiling intervals.
HASHMAP_TYPE<std::string_view, CaptureInterval> intervals{};
// profiling points
std::vector<blt::flat_queue<CapturePoint>> cyclicPointsHistory{};
blt::flat_queue<CapturePoint> points{};
blt::flat_queue<CapturePoint> cyclicPoints{};
std::mutex timerLock{};
public:
profile() = default;
void finishCycle() {
cyclicPointsHistory.push_back(cyclicPoints);
// im not sure if this is the correct way to clear a queue, there is no function to do so.
cyclicPoints = {};
}
void startInterval(const std::string_view& name) {
std::scoped_lock lock(timerLock);
CaptureInterval interval{};
interval.start = System::getCurrentTimeNanoseconds();
intervals[name] = interval;
}
void endInterval(const std::string_view& name) {
std::scoped_lock lock(timerLock);
intervals[name].end = System::getCurrentTimeNanoseconds();
}
/**
* Records the current time for the purpose of reconstructing the execution time between points, in order to find the most common cause for performance issues.
* @param name a common name for the point which you are trying to profile. This name should be meaningful as it will be displayed in the output.
*/
void profilerPoint(const std::string_view& name) {
points.push(CapturePoint{name, System::getCurrentTimeNanoseconds()});
}
/**
* Records the current time for the purpose of reconstructing the execution time between points, in order to find the most common cause for performance issues.
* Uses a separate tracking device that will be reset when finishCycle(); is called.
* @param name a common name for the point which you are trying to profile. This name should be meaningful as it will be displayed in the output.
*/
void profilerPointCyclic(const std::string_view& name) {
cyclicPoints.push(CapturePoint{name, System::getCurrentTimeNanoseconds()});
}
void print(){
// TODO:
for (auto c : intervals){
std::cout << c.first << " " << c.second.start << " " << c.second.end << ": " << std::to_string((c.second.end - c.second.start)/1000000) << "\n";
}
}
}; };
class Profiler { void startInterval(const std::string& profileName, const std::string& intervalName);
private: void endInterval(const std::string& profileName, const std::string& intervalName);
public: void point(const std::string& profileName, const std::string& pointName);
}; CaptureInterval getInterval(const std::string& profileName, const std::string& intervalName);
Profile getProfile(const std::string& profileName);
void createProfiler(Profiler* profiler); void printProfile(const std::string& profileName, int loggingLevel);
void printOrderedProfile(const std::string& profileName, int loggingLevel);
void discardProfiles();
void discardIntervals(const std::string& profileName);
void discardPoints(const std::string& profileName);
} }
#endif //BLT_PROFILER_H #endif //BLT_PROFILER_H
#ifdef BLT_DISABLE_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)
#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);
#endif

View File

@ -20,6 +20,7 @@ namespace blt::logging {
bool m_logToConsole = true; bool m_logToConsole = true;
bool m_logToFile = true; bool m_logToFile = true;
const char* m_directory = "./"; const char* m_directory = "./";
LOG_LEVEL minLevel = TRACE;
explicit constexpr LOG_PROPERTIES(bool useColor, bool logToConsole, bool logToFile, const char* directory): explicit constexpr LOG_PROPERTIES(bool useColor, bool logToConsole, bool logToFile, const char* directory):
m_useColor(useColor), m_logToConsole(logToConsole), m_logToFile(logToFile), m_directory(directory) {} m_useColor(useColor), m_logToConsole(logToConsole), m_logToFile(logToFile), m_directory(directory) {}
@ -32,11 +33,11 @@ namespace blt::logging {
void logi(const std::string& str) const; void logi(const std::string& str) const;
// evil hack, todo: better way // evil hack, todo: better way
#ifdef BLT_DISABLE_LOGGING #ifdef BLT_DISABLE_LOGGING
void log(const std::string& str) { void log(const std::string& str) const {
} }
#else #else
void log(const std::string& str) { void log(const std::string& str) const {
logi(str); logi(str);
} }
#endif #endif
@ -49,6 +50,11 @@ namespace blt::logging {
static logger elog{ERROR}; static logger elog{ERROR};
static logger flog{FATAL}; static logger flog{FATAL};
/**
* Always in order of the enum!
*/
static logger loggerLevelDecode[6]{tlog, dlog, ilog, wlog, elog, flog};
static logger trace{TRACE}; static logger trace{TRACE};
static logger debug{DEBUG}; static logger debug{DEBUG};
static logger info{INFO}; static logger info{INFO};
@ -126,19 +132,12 @@ namespace blt::logging {
} }
#ifdef BLT_DISABLE_LOGGING #ifdef BLT_DISABLE_LOGGING
#define BLT_TRACE(format, args...) #define BLT_TRACE(format, ...)
#define BLT_DEBUG(format, args...) #define BLT_DEBUG(format, ...)
#define BLT_INFO(format, args...) #define BLT_INFO(format, ...)
#define BLT_WARN(format, args...) #define BLT_WARN(format, ...)
#define BLT_ERROR(format, args...) #define BLT_ERROR(format, ...)
#define BLT_FATAL(format, args...) #define BLT_FATAL(format, ...)
#define BLT_TRACE_LN(format, args...)
#define BLT_DEBUG_LN(format, args...)
#define BLT_INFO_LN(format, args...)
#define BLT_WARN_LN(format, args...)
#define BLT_ERROR_LN(format, args...)
#define BLT_FATAL_LN(format, args...)
#else #else
/*#define BLT_TRACE(format, ...) log(format, blt::logging::TRACE, false, ##__VA_ARGS__); /*#define BLT_TRACE(format, ...) log(format, blt::logging::TRACE, false, ##__VA_ARGS__);
#define BLT_DEBUG(format, ...) log(format, blt::logging::DEBUG, false, ##__VA_ARGS__); #define BLT_DEBUG(format, ...) log(format, blt::logging::DEBUG, false, ##__VA_ARGS__);

View File

@ -117,7 +117,7 @@ namespace blt {
public: public:
void push(const T& t) { void push(const T& t) {
if (m_insertIndex >= m_size) { if (m_insertIndex+1 >= m_size) {
expand(m_size * 2); expand(m_size * 2);
} }
m_data[m_insertIndex++] = t; m_data[m_insertIndex++] = t;
@ -147,6 +147,14 @@ namespace blt {
return m_insertIndex - m_headIndex; return m_insertIndex - m_headIndex;
} }
T* begin(){
return m_data[m_headIndex];
}
T* end(){
return m_data[m_insertIndex];
}
~flat_queue() { ~flat_queue() {
delete[](m_data); delete[](m_data);
} }

View File

@ -4,9 +4,60 @@
* See LICENSE file for license detail * See LICENSE file for license detail
*/ */
#include <blt/profiling/profiler.h> #include <blt/profiling/profiler.h>
#include <mutex>
#include <vector>
#include <blt/std/time.h>
#include <blt/std/logging.h>
#include <iostream>
namespace blt { namespace blt::profiling {
void createProfiler(Profiler* profiler) {
// TODO: a better way
std::mutex profileLock{};
std::unordered_map<std::string, Profile> 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) {
} }
CaptureInterval getInterval(const std::string& profileName, const std::string& intervalName) {
return profiles[profileName].intervals[intervalName];
}
Profile getProfile(const std::string& profileName) {
return profiles[profileName];
}
void printProfile(const std::string& profileName, int loggingLevel) {
//auto& out = loggingLevel < 0 ? std::cout : logging::loggerLevelDecode[loggingLevel];
}
void printOrderedProfile(const std::string& profileName, int loggingLevel) {
}
void discardProfiles() {
profiles = {};
}
void discardIntervals(const std::string& profileName) {
profiles[profileName].intervals = {};
}
void discardPoints(const std::string& profileName) {
profiles[profileName].points = {};
}
} }

View File

@ -94,6 +94,8 @@ namespace blt::logging {
} }
inline void log(const std::string& str, bool hasEndingLinefeed, LOG_LEVEL level, int auto_line){ inline void log(const std::string& str, bool hasEndingLinefeed, LOG_LEVEL level, int auto_line){
if (level < BLT_LOGGING_PROPERTIES.minLevel)
return;
std::string outputString = System::getTimeStringLog(); std::string outputString = System::getTimeStringLog();
outputString += levelNames[level]; outputString += levelNames[level];
outputString += str; outputString += str;