Better profiler
parent
bc4bf76be7
commit
e58f20d16e
|
@ -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()
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
|
@ -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__);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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 = {};
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue