spacebox/src/time_it.hpp

94 lines
2.9 KiB
C++

/* /\ +------------------------------------------------------+
* ____/ \____ /| - Open source game framework licensed to freely use, |
* \ / / | copy, modify and sell without restriction |
* +--\ ^__^ /--+ | |
* | ~/ \~ | | - created for <https://foam.shampoo.ooo> |
* | ~~~~~~~~~~~~ | +------------------------------------------------------+
* | SPACE ~~~~~ | /
* | ~~~~~~~ BOX |/
* +--------------+
*
* time_it
* =======
*
* This class is used for printing the running time of a function or lambda. It can be
* inserted inline into existing code by wrapping the block to time in a lambda. It can also be
* given a function and optionally the function's arguments and will return a value of the type specified.
*
* The following code
*
* ~~~{.cpp}
* std::string fake(std::string x, std::string y)
* {
* return x + y;
* }
*
* // Needs SPACEBOX initialization for log call
* int ii = 0;
* time_it()([&] { while (ii++ < 1000); });
* ii = 0;
* int revolving = time_it<int, int>("for revolving")([&](int x) -> int { while (ii++ < 10000); return x; }, 1);
* ii = 0;
* std::cout << "Revolving is " << revolving << std::endl;
* std::string addition = time_it<std::string, std::string, std::string>("for combination")(fake, "Hello, ", "World!");
* std::cout << "Combination is " << addition << std::endl;
* time_it("for many combinations")([&] { while (ii++ < 100000) { fake("a", "b"); } });
* ~~~
*
* gives the expected output
*
* Elapsed time: 2.588e-06s
* Elapsed time for revolving: 2.1547e-05s
* Revolving is 1
* Elapsed time for combination: 7.27e-07s
* Combination is Hello, World!
* Elapsed time for many combinations: 0.0107351s
*/
#pragma once
#include <string>
#include <iostream>
#include <chrono>
#include <functional>
#include <type_traits>
template<typename return_type = void, typename... arguments>
class time_it
{
private:
std::string info = "";
public:
time_it(std::string info = "") : info(info) {};
return_type operator()(const std::function<return_type(arguments...)>&& block, arguments... args)
{
std::cout << "{Elapsed time";
if (!info.empty())
{
std::cout << " " << info;
}
std::cout << ": ";
auto start = std::chrono::steady_clock::now();
std::chrono::duration<float> elapsed;
if constexpr (std::is_same_v<return_type, void>)
{
block(args...);
elapsed = std::chrono::steady_clock::now() - start;
std::cout << elapsed.count() << "s}" << std::endl;
}
else
{
return_type result = block(args...);
elapsed = std::chrono::steady_clock::now() - start;
std::cout << elapsed.count() << "s}" << std::endl;
return result;
}
}
};