flatten 20260225

This commit is contained in:
Timothy Prepscius
2026-02-25 12:39:24 -05:00
commit fa54be052a
315 changed files with 49791 additions and 0 deletions

View File

@@ -0,0 +1,150 @@
// TJP COPYRIGHT HEADER
#include "PROFILE_SCOPE.h"
#include <sstream>
#include <list>
#include <iomanip>
#include <tjp/core/threads/Lock.hpp>
#include <tjp/core/timer/Timer.hpp>
#include <tjp/core/log/Log.h>
#include <tjp/core/log/LogOf.h>
#include <tjp/core/algorithm/starts_with.hpp>
#include <tjp/core/assert/debug_assert.h>
#include <iostream>
namespace tjp {
namespace core {
namespace profile_scope {
void ProfileScopeManager::append (ProfileToken *token)
{
auto lock = lock_of(mutex);
tokens.push_back(token);
}
std::ostream &ProfileScopeManager::print (std::ostream &s)
{
auto l = lock_of(mutex);
return print_no_lock(s);
}
std::ostream &ProfileScopeManager::print_no_lock (std::ostream &s)
{
Timepoint now = Clock::now();
Timepoint then = now - std::chrono::milliseconds(1000);
s << std::setprecision(10) << std::fixed << std::showpoint;
struct TokenStats {
ProfileToken *token;
Stats stats;
} ;
std::vector<TokenStats> sortedStats;
for (auto &token : tokens)
{
Stats stats = token->getStats(then);
if (stats.count > 0)
{
sortedStats.push_back({ token, stats });
}
}
std::sort(sortedStats.begin(), sortedStats.end(), [](auto &l, auto &r) { return l.stats.totalDuration < r.stats.totalDuration; });
s << "\nPROFILE ---------------------";
for (auto &[token, stats] : sortedStats)
{
s << "\n";
s
<< "PROFILE\t" << token->name
<< ":\t" << stats.count
<< "\t" << std::chrono::duration_cast<std::chrono::nanoseconds>(stats.averageDuration).count() / (float)1e+9
<< "s\t" << std::chrono::duration_cast<std::chrono::nanoseconds>(stats.totalDuration).count() / (float)1e+9
<< "s";
}
return s;
}
std::ostream &ProfileScopeManager::print_clear (std::ostream &s)
{
auto l = lock_of(mutex);
auto &r = print_no_lock(s);
return r;
}
void profile_log ()
{
std::ostringstream s;
ProfileScopeManagerSingleton::getInstance()->print(s);
sLogRelease("profile", s.str());
}
// ------------------------------------------------------
ProfileToken::ProfileToken(const char *prettyFunction)
{
name = prettyFunction;
ProfileScopeManagerSingleton::getInstance()->append(this);
}
void ProfileToken::onRecord(ProfileRecord &&record)
{
auto l = lock_of(mutex);
records.emplace_back(std::move(record));
}
Stats ProfileToken::getStats (const Timepoint &then)
{
auto l = lock_of(mutex);
Duration duration = Duration::zero();
size_t count = 0;
for (auto &record : records)
{
if (record.end > then)
{
duration += record.duration;
count++;
}
}
if (count)
{
return Stats {
.count = count,
.totalDuration = duration,
.averageDuration = duration / count
};
}
return Stats { .count = 0 };
}
static bool profile_enabled_ = false;
void profile_enable()
{
xLogActivateStory("profile");
profile_enabled_ = true;
}
bool profile_enabled()
{
return profile_enabled_;
}
} // namespace
} // namespace
} // namespace

View File

@@ -0,0 +1,147 @@
// TJP COPYRIGHT HEADER
#pragma once
#include <mutex>
#include <chrono>
#include <functional>
#include <sstream>
#include <list>
#include <map>
#include <vector>
#include <tjp/core/threads/Lock.hpp>
namespace tjp {
namespace core {
namespace profile_scope {
typedef std::chrono::high_resolution_clock Clock;
typedef std::chrono::time_point<Clock> Timepoint;
typedef Clock::duration Duration;
struct ProfileToken;
struct ProfileScopeManager
{
Mutex mutex;
std::vector<ProfileToken *> tokens;
public:
void append (ProfileToken *token);
std::ostream &print (std::ostream &s);
std::ostream &print_no_lock (std::ostream &s);
std::ostream &print_clear (std::ostream &s);
} ;
template<typename T>
struct ProfileScopeManagerSingleton_
{
static ProfileScopeManager *singleton;
static ProfileScopeManager *getInstance ()
{
if (!singleton)
singleton = new ProfileScopeManager();
return singleton;
}
} ;
template<typename T>
ProfileScopeManager *ProfileScopeManagerSingleton_<T>::singleton = nullptr;
using ProfileScopeManagerSingleton = ProfileScopeManagerSingleton_<void>;
struct ProfileRecord
{
Timepoint begin, end;
Duration duration;
const void *other;
} ;
struct Stats
{
size_t count;
Duration totalDuration, averageDuration;
} ;
struct ProfileToken
{
std::string name;
Mutex mutex;
std::vector<ProfileRecord> records;
ProfileToken(const char *prettyFunction);
void onRecord(ProfileRecord &&record);
Stats getStats (const Timepoint &then);
} ;
void profile_enable();
bool profile_enabled();
struct ProfileScope
{
bool enabled;
ProfileToken *token;
ProfileRecord record;
ProfileScope(ProfileToken *token_, const void *other = nullptr) :
token(token_),
enabled(profile_enabled())
{
if (enabled)
{
record.other = other;
record.begin = Clock::now();
}
}
~ProfileScope()
{
if (enabled)
{
record.end = Clock::now();
record.duration = record.end - record.begin;
token->onRecord(std::move(record));
}
}
} ;
void profile_log();
} // namespace
} // namespace
} // namespace
#ifdef _DEBUG
//#define USE_PROFILE
#endif
#ifdef USE_PROFILE
#define PROFILE_SCOPE(...) \
static tjp::core::profile_scope::ProfileToken __profile_token__(__PRETTY_FUNCTION__); \
tjp::core::profile_scope::ProfileScope __profile_scope__(&__profile_token__, __VA_ARGS__)
#define PROFILE_FUNCTION(...) PROFILE_SCOPE(__VA_ARGS__)
#define PROFILE_LOG() tjp::core::profile_scope::profile_log()
#define PROFILE_ENABLE() tjp::core::profile_scope::profile_enable()
#else
#define PROFILE_SCOPE(...)
#define PROFILE_FUNCTION(...)
#define PROFILE_LOG()
#define PROFILE_ENABLE()
#endif

View File

@@ -0,0 +1,106 @@
// TJP COPYRIGHT HEADER
#define TESTING
#include "PROFILE_SIGNAL.h"
#include <sstream>
#include <list>
#include <tjp/core/threads/Lock.hpp>
#include <tjp/core/timer/Timer.hpp>
#include <tjp/core/log/Log.h>
#include <tjp/core/log/LogOf.h>
#include <tjp/core/assert/debug_assert.h>
#include <tjp/core/time/Time+IO.hpp>
#include <iostream>
namespace tjp {
namespace core {
void ProfileSignal::clear ()
{
auto l = lock_of(mutex);
clear_no_lock();
}
void ProfileSignal::clear_no_lock ()
{
timers.clear();
times.clear();
cleared = true;
}
std::ostream &ProfileSignal::print (std::ostream &s)
{
auto l = lock_of(mutex);
return print_no_lock(s);
}
std::ostream &ProfileSignal::print_no_lock (std::ostream &s)
{
for (auto &[e, ts] : times)
{
s << "\t" << e;
for (auto &t : ts)
{
s << "\t" << t;
}
s << std::endl;
}
return s;
}
std::ostream &ProfileSignal::print_clear (std::ostream &s)
{
auto l = lock_of(mutex);
auto &r = print_no_lock(s);
clear_no_lock();
return r;
}
void ProfileSignal::begin (Event &&e)
{
auto l = lock_of(mutex);
auto time = timeSource.get();
auto i = timers.find(e);
if (i != timers.end())
return;
timers[e] = time;
signal.notify_all();
}
void ProfileSignal::end (Event &&e)
{
auto l = lock_of(mutex);
auto i = timers.find(e);
if (i != timers.end())
{
auto then = i->second;
auto now = timeSource.get();
auto dt = now-then;
times[e].push_back(dt);
std::ostringstream s;
sLogDebug("profile_signal", e << "\t" << dt << ((dt > time::Deciseconds(1)) ? " dt-large" : ""));
std::cout << s.str();
timers.erase(i);
}
signal.notify_all();
}
} // namespace
} // namespace

View File

@@ -0,0 +1,144 @@
// TJP COPYRIGHT HEADER
#pragma once
#ifdef TESTING
#include <tjp/core/threads/Lock.hpp>
#include <tjp/core/timer/Timer.hpp>
#include <tjp/core/time/Time.h>
#include <tjp/core/time/Source.hpp>
#include <functional>
#include <sstream>
#include <list>
#include <map>
#include <vector>
namespace tjp {
namespace core {
struct ProfileSignal
{
typedef std::string Event;
core::Event::Mutex mutex;
core::Event signal;
bool cleared = false;
typedef time::Time Time;
typedef time::Duration Duration;
time::SourceStandard timeSource;
std::map<Event, Time> timers;
std::map<Event, std::vector<Duration>> times;
typedef std::list<Event> Events;
Events events;
public:
void append (Event &&e);
const std::string STAR = "*";
void begin(Event &&e);
void end(Event &&e);
void clear();
void clear_no_lock();
std::ostream &print (std::ostream &s);
std::ostream &print_no_lock (std::ostream &s);
std::ostream &print_clear (std::ostream &s);
} ;
template<typename T>
struct ProfileSignalSingleton
{
static ProfileSignal *singleton;
static ProfileSignal *getInstance ()
{
if (!singleton)
singleton = new ProfileSignal();
return singleton;
}
} ;
template<typename T>
ProfileSignal *ProfileSignalSingleton<T>::singleton = nullptr;
// -------
template<typename S, typename T, typename ...X>
void profile_test_event_string_args(S &s, T &t)
{
s << t;
}
template<typename S, typename T, typename ...X>
void profile_test_event_string_args(S &s, T &&t, X&&...x)
{
s << t << ",";
profile_test_event_string_args(s, x...);
}
template<typename ... T>
std::string profile_test_event_string(T&& ...t)
{
std::ostringstream s;
profile_test_event_string_args(s, t...);
return s.str();
}
template<typename...T>
void profile_time_clear()
{
ProfileSignalSingleton<void>::getInstance()->clear ();
}
template<typename S>
S &profile_time_print(S &stream)
{
return ProfileSignalSingleton<void>::getInstance()->print (stream);
}
template<typename S>
S &process_time_print_clear(S &stream)
{
return ProfileSignalSingleton<void>::getInstance()->print_clear (stream);
}
template<typename...T>
void profile_time_begin(T&&...t)
{
ProfileSignalSingleton<void>::getInstance()->begin (ProfileSignal::Event{ process_test_event_string(t...) });
}
template<typename...T>
void profile_time_end(T&&...t)
{
return ProfileSignalSingleton<void>::getInstance()->end(ProfileSignal::Event{ process_test_event_string(t...) });
}
} // namespace
} // namespace
#define TEST_TIME_CLEAR() tjp::core::profile_time_clear()
#define TEST_TIME_PRINT(stream) tjp::core::profile_time_print(stream)
#define TEST_TIME_PRINT_CLEAR(stream) tjp::core::profile_time_print_clear(stream)
#define TEST_TIME_BEGIN(v,...) tjp::core::profile_time_begin(v,__VA_ARGS__)
#define TEST_TIME_END(v,...) tjp::core::profile_time_end(v,__VA_ARGS__)
#else
#define TEST_TIME_BEGIN(...)
#define TEST_TIME_END(...)
#endif