C++ 使用 std::chrono 以一种很好的方式测量成员函数的执行 [英] C++ use std::chrono to measure execution of member functions in a nice way
问题描述
我想优化我的应用程序,尤其是某些功能的执行速度.
I want to optimize my application, especially the execution speed of certain functions.
想象有一个带有一些成员函数的类
Imagine there is a class with some member functions
class Test
{
public:
Test();
virtual ~Test();
int init(int arg1, double arg2);
private:
[...]
在我的构造函数中,我调用这些方法之一
and in my constructor I call one of these methods
Test::Test()
{
[...]
int value = init(1, 1.2);
}
如何在不破坏我的程序的情况下以一种干净整洁的方式测量我的方法 init(...)
的执行时间?
How can I measure the execution time of my method init(...)
in a nice and clean way without breaking my program?
目前我使用以下代码
Test::Test()
{
[...]
auto start = std::chrono::high_resolution_clock::now();
int value = init(1, 1.2);
auto stop = std::chrono::high_resolution_clock::now();
std::chrono::duration<double> duration = stop - start;
std::cout << duration.count() * 1000 << "ms\n";
}
它按预期工作,但我认为它非常混乱,我想要一个更干净"的解决方案.
It works as expected but I think it is pretty messy and I want to have a "cleaner" solution.
有没有办法让某种函数像这样接受成员函数和其他参数
Is there a way to have some kind of function which takes a member function and other parameters like so
int value = countTime(function, arg1, arg2);
我不知道是否可以将 function()
的返回值传递给 countTime()
以便不中断我的工作流程代码.
I don't know whether it is possible to pass the return value from function()
to countTime()
in order to don't interrupt the workflow of my code.
这是我的 TimeMeasure 课
This is my TimeMeasure class
namespace tools
{
class TimeMeasure
{
public:
TimeMeasure()
{
m_start = std::chrono::high_resolution_clock::now();
}
virtual ~TimeMeasure()
{
m_stop = std::chrono::high_resolution_clock::now();
std::chrono::duration<double, std::milli> duration = m_stop - m_start;
std::cout << duration.count() << "ms\n";
}
public:
typedef std::chrono::time_point<std::chrono::high_resolution_clock> HighResClock;
private:
HighResClock m_start;
HighResClock m_stop;
};
template <typename T, typename F, typename... Args>
auto measure(T *t, F &&fn, Args... args)
{
tools::TimeMeasure timeMeasure;
return (t->*fn)(std::forward<Args>(args)...);
}
}
在我的构造函数 Test()
中,我以这种方式使用函数 measure
and in my constructor Test()
I use the function measure
this way
Test()
{
[...]
tools::measure(this, Test::init, filepath);
}
int init(const std::string& filepath) const
在这里将字符串转换为文件.所以就我而言,这只是一个论点
int init(const std::string& filepath) const
takes here a string to a file. So in my case it's just one argument
不幸的是,我得到一个 invalid use of non-static member function 'int init(const string&) const'
错误
Unfortunately I get a invalid use of non-static member function 'int init(const string&) const'
error
我想知道构造函数是否不是成员函数.那么为什么我会收到这个错误?
I would wonder if a constructor is not a member function. So why do I get this error?
编辑 2:
根据 OznOg 的回答,我只是忘记提交指向我的函数的指针.
According to OznOg's answer I just forgot to hand in a pointer to my function.
所以这将是正确的函数调用
So this would be the correct function call
tools::measure(this, &Test::init, filepath);
推荐答案
你可以创建一个类:
struct MeasureTime {
MeasureTime() : _start(std::chrono::high_resolution_clock::now()) {}
~MeasureTime() {
auto stop = std::chrono::high_resolution_clock::now();
std::chrono::duration<double> duration = stop - _start;
std::cout << duration.count() * 1000 << "ms\n";
}
private:
std::chrono::time_point<std::chrono::high_resolution_clock> _start;
};
并且只需在您的代码中使用它:
and simply use it in your code:
Test::Test()
{
MeasureTime mt;
[...]
{ //or even this for just the init call
MeasureTime mt2;
int value = init(1, 1.2);
}
}
恕我直言,它没有你提出的那样具有侵入性.
IMHO it is less intrusive than what you proposed.
如果你真的想要一个函数,你可以试试这样的包装器:
If you really want a function, you may try a wrapper like:
template <class T, class F, class... Args>
auto MeasureTimeFn(T *t, F &&fn, Args&&... args) {
MeasureTime timer;
return (t->*fn)(std::forward<Args>(args)...);
}
并称之为:
int value = MeasureTimeFn(this, &Test::init, 1, 1.2);
但不确定它真的好多了.
but not sure it is really much better.
您可以尝试使用宏隐藏内容:
You can try to hide thing with a macro:
#define MEASURE(f, ...) \
MeasureTimeFn(this, &std::remove_reference_t<decltype(*this)>::f, __VA_ARGS__)
这样你就可以写
int value = MEASURE(init, 1, 1.2);
与您要求的非常相似,但只能在成员函数内部使用,并且具有成员函数(非静态).
what is quite like what you asked for, but only works inside member functions, with member functions (non static).
无论如何可能是一个很好的起点.
Anyway probably a good place to start with.
* 编辑*如果你可以修改你的类的继承,你可以试试
* EDIT* If you can modify inheritance of you class, you may try
template<class T>
struct MeasureTool {
template <class F, class... Args>
auto measure(F &&fn, Args&&... args) {
tools::TimeMeasure timeMeasure;
return (static_cast<T*>(this)->*fn)(std::forward<Args>(args)...);
}
};
class Test : public MeasureTool<Test>
{
public:
Test();
virtual ~Test() {}
int init(const std::string &filepath) { _path = filepath; return 0; }
const auto &getPath() const { return _path; }
private:
std::string _path;
};
Test::Test()
{
std::string filepath("/some/where");
int value = measure(&Test::init, filepath);
measure(&Test::getPath);
}
而且,这一次,似乎符合您的第一个要求(但非常具有侵入性...)
And, this time, seems to match your very first requirement (but is quite intrusive...)
现在,一切都在你手中:)
now, it's all in your hands :)
这篇关于C++ 使用 std::chrono 以一种很好的方式测量成员函数的执行的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!