| @@ -0,0 +1,13 @@ | |||||
| TIMEFORMAT=%3lR | |||||
| SCRIPTPATH="$( cd "$(dirname "$0")" ; pwd -P )" | |||||
| pushd $SCRIPTPATH > /dev/null | |||||
| # _DEBUG | |||||
| # time g++ -fpermissive src/main.cpp -g -o ./bin/slime --std=c++17 || exit 1 | |||||
| time clang++ -D_DEBUG -D_PROFILING -fpermissive test.cpp -g -o ./ftb --std=c++17 || exit 1 | |||||
| echo "" | |||||
| time ./ftb | |||||
| popd > /dev/null | |||||
| unset TIMEFORMAT | |||||
| @@ -1,54 +0,0 @@ | |||||
| #pragma once | |||||
| #include <functional> | |||||
| #define proc auto | |||||
| #ifdef _DEBUG | |||||
| # define if_debug if constexpr (true) | |||||
| #else | |||||
| # define if_debug if constexpr (false) | |||||
| #endif | |||||
| #ifdef _MSC_VER | |||||
| # define debug_break() if_debug __debugbreak() | |||||
| # define if_windows if constexpr (true) | |||||
| # define if_linux if constexpr (false) | |||||
| #else | |||||
| # define debug_break() if_debug raise(SIGTRAP) | |||||
| # define if_windows if constexpr (false) | |||||
| # define if_linux if constexpr (true) | |||||
| #endif | |||||
| /** | |||||
| * Defer * | |||||
| */ | |||||
| template<typename F> | |||||
| class defer_finalizer { | |||||
| F f; | |||||
| bool moved; | |||||
| public: | |||||
| template<typename T> | |||||
| defer_finalizer(T && f_) : f(std::forward<T>(f_)), moved(false) { } | |||||
| defer_finalizer(const defer_finalizer &) = delete; | |||||
| defer_finalizer(defer_finalizer && other) : f(std::move(other.f)), moved(other.moved) { | |||||
| other.moved = true; | |||||
| } | |||||
| ~defer_finalizer() { | |||||
| if (!moved) f(); | |||||
| } | |||||
| }; | |||||
| struct { | |||||
| template<typename F> | |||||
| defer_finalizer<F> operator<<(F && f) { | |||||
| return defer_finalizer<F>(std::forward<F>(f)); | |||||
| } | |||||
| } deferrer; | |||||
| #define TOKENPASTE(x, y) x ## y | |||||
| #define TOKENPASTE2(x, y) TOKENPASTE(x, y) | |||||
| #define defer auto TOKENPASTE2(__deferred_lambda_call, __COUNTER__) = deferrer << [&] | |||||
| @@ -0,0 +1,77 @@ | |||||
| #pragma once | |||||
| #include <functional> | |||||
| #define proc auto | |||||
| #ifdef _DEBUG | |||||
| # define if_debug if constexpr (true) | |||||
| #else | |||||
| # define if_debug if constexpr (false) | |||||
| #endif | |||||
| #ifdef _MSC_VER | |||||
| # define debug_break() if_debug __debugbreak() | |||||
| # define if_windows if constexpr (true) | |||||
| # define if_linux if constexpr (false) | |||||
| #else | |||||
| # define debug_break() if_debug raise(SIGTRAP) | |||||
| # define if_windows if constexpr (false) | |||||
| # define if_linux if constexpr (true) | |||||
| #endif | |||||
| #define TOKENPASTE(x, y) x ## y | |||||
| #define TOKENPASTE2(x, y) TOKENPASTE(x, y) | |||||
| /** | |||||
| * Defer * | |||||
| */ | |||||
| template<typename F> | |||||
| class defer_finalizer { | |||||
| F f; | |||||
| bool moved; | |||||
| public: | |||||
| template<typename T> | |||||
| defer_finalizer(T && f_) : f(std::forward<T>(f_)), moved(false) { } | |||||
| defer_finalizer(const defer_finalizer &) = delete; | |||||
| defer_finalizer(defer_finalizer && other) : f(std::move(other.f)), moved(other.moved) { | |||||
| other.moved = true; | |||||
| } | |||||
| ~defer_finalizer() { | |||||
| if (!moved) f(); | |||||
| } | |||||
| }; | |||||
| struct { | |||||
| template<typename F> | |||||
| defer_finalizer<F> operator<<(F && f) { | |||||
| return defer_finalizer<F>(std::forward<F>(f)); | |||||
| } | |||||
| } deferrer; | |||||
| #define defer auto TOKENPASTE2(__deferred_lambda_call, __COUNTER__) = deferrer << [&] | |||||
| /** | |||||
| * fluid-let * | |||||
| */ | |||||
| #define fluid_let(var, val) \ | |||||
| if (0) \ | |||||
| TOKENPASTE2(finished,__LINE__): ; \ | |||||
| else \ | |||||
| for (auto TOKENPASTE2(fluid_let_, __LINE__) = var;;) \ | |||||
| for(var = val;;) \ | |||||
| if (1) { \ | |||||
| goto TOKENPASTE2(body,__LINE__); \ | |||||
| } \ | |||||
| else \ | |||||
| while (1) \ | |||||
| if (1) { \ | |||||
| var = TOKENPASTE2(fluid_let_, __LINE__); \ | |||||
| goto TOKENPASTE2(finished, __LINE__); \ | |||||
| } \ | |||||
| else TOKENPASTE2(body,__LINE__): | |||||
| @@ -1,40 +0,0 @@ | |||||
| #pragma once | |||||
| #include <stdio.h> | |||||
| #include <string.h> | |||||
| #include <time.h> | |||||
| struct Profiler { | |||||
| inline thread_local static int thread_id = 0; | |||||
| inline thread_local static FILE* out_file = nullptr; | |||||
| inline static char file_template[40] = "\0"; | |||||
| Profiler(const char* file, const char* func, const int line) { | |||||
| if (!out_file) { | |||||
| time_t t = time(NULL); | |||||
| tm tm_i; | |||||
| localtime_s(&tm_i, &t); | |||||
| if (!file_template[0]) { | |||||
| sprintf(file_template, "%02d.%02d.%04d-%02d.%02d.%02d-%%02d-profiler.report", | |||||
| tm_i.tm_mday, tm_i.tm_mon+1, tm_i.tm_year+1900, | |||||
| tm_i.tm_hour, tm_i.tm_min, tm_i.tm_sec); | |||||
| } | |||||
| char file_name[38]; | |||||
| sprintf(file_name, file_template, thread_id); | |||||
| fopen_s(&out_file, file_name, "w"); | |||||
| if (!out_file) { | |||||
| printf("could not open %s\n", file_name); | |||||
| } | |||||
| } | |||||
| fprintf(out_file, "-> %s %s %d\n", func, file, line); | |||||
| }; | |||||
| ~Profiler() { | |||||
| fprintf(out_file, "<-\n"); | |||||
| }; | |||||
| }; | |||||
| #define profile_this Profiler profiler(__FILE__, __FUNCTION__, __LINE__) | |||||
| @@ -0,0 +1,61 @@ | |||||
| #pragma once | |||||
| #ifdef _PROFILING | |||||
| # include <stdlib.h> | |||||
| # include <stdio.h> | |||||
| # include <string.h> | |||||
| # include <time.h> | |||||
| // for syscall: | |||||
| # include <unistd.h> | |||||
| # include <sys/syscall.h> | |||||
| struct Profiler { | |||||
| // same for all threads | |||||
| inline static char file_template[40] = "\0"; | |||||
| // thread local | |||||
| inline thread_local static bool is_initialized = false; | |||||
| inline thread_local static int thread_id = -1; | |||||
| inline thread_local static int call_depth = 0; | |||||
| inline thread_local static FILE* out_file = nullptr; | |||||
| Profiler(const char* file, const char* func, const int line) { | |||||
| call_depth += 1; | |||||
| // if we never used this thread before | |||||
| if (!is_initialized) { | |||||
| thread_id = syscall(__NR_gettid); | |||||
| printf("Hello I am %d\n", thread_id); | |||||
| time_t t = time(NULL); | |||||
| tm* tm_i = localtime(&t); | |||||
| // if we never even created the shared file name template | |||||
| if (!file_template[0]) { | |||||
| sprintf(file_template, "%02d.%02d.%04d-%02d.%02d.%02d-%%02d-profiler.report", | |||||
| tm_i->tm_mday, tm_i->tm_mon+1, tm_i->tm_year+1900, | |||||
| tm_i->tm_hour, tm_i->tm_min, tm_i->tm_sec); | |||||
| } | |||||
| char file_name[38]; | |||||
| sprintf(file_name, file_template, thread_id); | |||||
| out_file = fopen(file_name, "w"); | |||||
| if (!out_file) { | |||||
| printf("could not open %s\n", file_name); | |||||
| } | |||||
| is_initialized = true; | |||||
| } | |||||
| fprintf(out_file, "-> %s %s %d\n", func, file, line); | |||||
| }; | |||||
| ~Profiler() { | |||||
| call_depth -= 1; | |||||
| fprintf(out_file, "<-\n"); | |||||
| if (call_depth == 0) | |||||
| fflush(out_file); | |||||
| }; | |||||
| }; | |||||
| # define profile_this Profiler profiler(__FILE__, __FUNCTION__, __LINE__) | |||||
| #else | |||||
| # define profile_this enum {} | |||||
| #endif | |||||
| @@ -1,20 +1,25 @@ | |||||
| #define _CRT_SECURE_NO_WARNINGS | #define _CRT_SECURE_NO_WARNINGS | ||||
| #include <windows.h> | |||||
| #include "profiler.h" | |||||
| #include "profiler.hpp" | |||||
| #include "macros.h" | #include "macros.h" | ||||
| int var = 100; | |||||
| void test() { | void test() { | ||||
| profile_this; | profile_this; | ||||
| printf("var is %d\n", var); | |||||
| fluid_let (var, 200) { | |||||
| printf("var is %d\n", var); | |||||
| } | |||||
| printf("doing more work!\n"); | |||||
| printf("var is %d\n", var); | |||||
| } | } | ||||
| int main(int argc, char* argv[]) { | int main(int argc, char* argv[]) { | ||||
| profile_this; | profile_this; | ||||
| printf("doing some work and sleeping!\n"); | |||||
| Sleep(1000); // Sleep a seconds | |||||
| test(); | test(); | ||||
| return 0; | return 0; | ||||