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_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})
@ -20,6 +21,12 @@ else()
set(PROFILING_FILES "")
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.
if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/libraries/parallel-hashmap/CMakeLists.txt)
set(USE_PHMAPS)
@ -33,8 +40,9 @@ message("Profiler Files ${PROFILING_FILES}")
message("Source: ${CMAKE_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/)
if(${USE_PHMAPS})
target_link_libraries(BLT phmap)
endif()

View File

@ -32,6 +32,9 @@ BLT_TESTS_IS_TOP_LEVEL:STATIC=ON
//Value Computed by CMake
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_PROFILING:BOOL=ON

View File

@ -8,17 +8,17 @@
#define BLT_PROFILER_H
#include <string>
#include <string_view>
#include <mutex>
#include <vector>
#include <blt/std/time.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 {
std::string_view name;
long point;
std::string name;
long point {};
};
struct CaptureInterval {
@ -26,70 +26,63 @@ namespace blt {
long end;
};
/**
* @tparam HASHMAP_TYPE
*/
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 {
private:
public:
struct Profile {
std::unordered_map<std::string, CaptureInterval> intervals;
blt::flat_queue<CapturePoint> points;
};
void createProfiler(Profiler* profiler);
void startInterval(const std::string& profileName, const std::string& intervalName);
void endInterval(const std::string& profileName, const std::string& intervalName);
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 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
#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_logToFile = true;
const char* m_directory = "./";
LOG_LEVEL minLevel = TRACE;
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) {}
@ -32,11 +33,11 @@ namespace blt::logging {
void logi(const std::string& str) const;
// evil hack, todo: better way
#ifdef BLT_DISABLE_LOGGING
void log(const std::string& str) {
void log(const std::string& str) const {
}
#else
void log(const std::string& str) {
void log(const std::string& str) const {
logi(str);
}
#endif
@ -48,6 +49,11 @@ namespace blt::logging {
static logger wlog{WARN};
static logger elog{ERROR};
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 debug{DEBUG};
@ -126,19 +132,12 @@ namespace blt::logging {
}
#ifdef BLT_DISABLE_LOGGING
#define BLT_TRACE(format, args...)
#define BLT_DEBUG(format, args...)
#define BLT_INFO(format, args...)
#define BLT_WARN(format, args...)
#define BLT_ERROR(format, args...)
#define BLT_FATAL(format, args...)
#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...)
#define BLT_TRACE(format, ...)
#define BLT_DEBUG(format, ...)
#define BLT_INFO(format, ...)
#define BLT_WARN(format, ...)
#define BLT_ERROR(format, ...)
#define BLT_FATAL(format, ...)
#else
/*#define BLT_TRACE(format, ...) log(format, blt::logging::TRACE, false, ##__VA_ARGS__);
#define BLT_DEBUG(format, ...) log(format, blt::logging::DEBUG, false, ##__VA_ARGS__);

View File

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

View File

@ -4,9 +4,60 @@
* See LICENSE file for license detail
*/
#include <blt/profiling/profiler.h>
#include <mutex>
#include <vector>
#include <blt/std/time.h>
#include <blt/std/logging.h>
#include <iostream>
namespace blt {
void createProfiler(Profiler* profiler) {
namespace blt::profiling {
// 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){
if (level < BLT_LOGGING_PROPERTIES.minLevel)
return;
std::string outputString = System::getTimeStringLog();
outputString += levelNames[level];
outputString += str;