我想优化我的应用程序,尤其是某些功能的执行速度。
想象有一个带有一些成员函数的类
class Test
{
public:
Test();
virtual ~Test();
int init(int arg1, double arg2);
private:
[...]
在我的构造函数中,我调用这些方法之一
Test::Test()
{
[...]
int value = init(1, 1.2);
}
如何在不破坏程序的情况下以一种简洁的方式来衡量方法init(...)
的执行时间?
此刻我使用以下代码
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";
}
它可以按预期工作,但我认为它很杂乱,我想拥有一个“更清洁”的解决方案。
有没有一种方法可以接受成员函数和其他类似参数的功能
int value = countTime(function, arg1, arg2);
我不知道是否可以将返回值从function()
传递到countTime()
,以便不中断代码的工作流程。
编辑: 这是我的TimeMeasure课
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
Test()
{
[...]
tools::measure(this, Test::init, filepath);
}
int init(const std::string& filepath) const
在这里将字符串添加到文件中。所以就我而言,这只是一个论点
不幸的是,我遇到了invalid use of non-static member function 'int init(const string&) const'
错误
我想知道构造函数是否不是成员函数。那么为什么会出现此错误?
编辑2:
根据OznOg的回答,我只是忘记了提供指向函数的指针。
这将是正确的函数调用
tools::measure(this, &Test::init, filepath);
答案 0 :(得分:4)
您可以创建一个像这样的类:
Optional
,只需在您的代码中使用它即可:
Maybe
恕我直言,它不如您建议的那样侵入。
如果您真的想要一个函数,可以尝试使用以下包装器:
Only
并这样称呼:
function accum(s) {
let str = s.toLowerCase();
let arr = [];
for(let i=0; i<str.length;i++){
arr.push(str[i].repeat(i+1));
var [firstLetter, ...rest] = arr[i]
arr[i] = firstLetter.toUpperCase() +rest.join('')
}
return arr.join('-');
}
但不确定它是否真的好很多。
您可以尝试使用宏隐藏事物:
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;
};
这样您就可以写
Test::Test()
{
MeasureTime mt;
[...]
{ //or even this for just the init call
MeasureTime mt2;
int value = init(1, 1.2);
}
}
与您所要求的完全一样,但是仅在成员函数内起作用,并且具有成员函数(非静态)。
无论如何,可能都是一个不错的起点。
*编辑* 如果您可以修改类的继承,则可以尝试
template <class T, class F, class... Args>
auto MeasureTimeFn(T *t, F &&fn, Args... args) {
MeasureTime timer;
return (t->*fn)(std::forward<Args>(args)...);
}
而且,这一次似乎符合您的第一个要求(但很麻烦……)
现在,一切都在您手中:)
答案 1 :(得分:0)
我总是使用Boost.Timer。
#include <boost/timer/timer.hpp>
...
boost::timer::cpu_timer timer;
for(int i = 0; i < 1000; ++i)
funct();
std::cout << timer.format();
它显示墙,用户和系统时间。
答案 2 :(得分:-1)
您可以使用以下实现方式:
#Create a list of items you are interested in (this is a set - only uniques)
itemstofind = {'Country Code', 'Country Location', 'Date', 'Population', 'Religion:'}
# use a dict comprehension to find the items and take next item in the list
# assumes there is no error in the data
d = {item:longlist[ind+1] for ind, item in enumerate(longlist) if item in itemstofind}
在void(*)(...)函数的情况下,它将返回一个具有成员持续时间的元组;在函数返回smth的情况下,将返回具有持续时间和返回类型的元组。它与std :: bind和成员函数一起使用。可能将重载合并到一个或两个实现中,但是我不知道该怎么做。
示例调用:
template<typename Fn, typename... Args>
typename std::enable_if<!std::is_void<typename std::result_of<Fn&&(Args...)>::type>::value,
std::tuple<std::chrono::duration<double>, typename std::result_of<Fn&&(Args...)>::type>
>::type
countTime(Fn&& fn, Args&&... args) {
auto start = std::chrono::high_resolution_clock::now();
auto fnret = std::forward<Fn>(fn)(std::forward<Args>(args)...);
auto stop = std::chrono::high_resolution_clock::now();
return std::make_tuple(stop - start, fnret);
}
template<typename Fn, typename... Args>
typename std::enable_if<std::is_void<typename std::result_of<Fn&&(Args...)>::type>::value,
std::tuple<std::chrono::duration<double>>
>::type
countTime(Fn&& fn, Args&&... args) {
auto start = std::chrono::high_resolution_clock::now();
std::forward<Fn>(fn)(std::forward<Args>(args)...);
auto stop = std::chrono::high_resolution_clock::now();
return std::make_tuple(stop - start);
}
template<typename R, class C, typename... Args>
typename std::enable_if<!std::is_same<R, void>::value,
std::tuple<std::chrono::duration<double>, R>
>::type
countTime(R (C::*fn)(Args...), C& obj, Args&&... args) {
auto start = std::chrono::high_resolution_clock::now();
auto fnret = (obj.*fn)(std::forward<Args>(args)...);
auto stop = std::chrono::high_resolution_clock::now();
return std::make_tuple(stop - start, fnret);
}
template<class C, typename... Args>
std::tuple<std::chrono::duration<double>>
countTime(void (C::*fn)(Args...), C& obj, Args&&... args) {
auto start = std::chrono::high_resolution_clock::now();
(obj.*fn)(std::forward<Args>(args)...);
auto stop = std::chrono::high_resolution_clock::now();
return std::make_tuple(stop - start);
}
简单的示例调用:
auto ret = countTime([](int a) -> int {
std::this_thread::sleep_for(std::chrono::milliseconds(a));
return a * 2;
}, 10);
std::cout << "function executed in: " <<
std::chrono::duration_cast<std::chrono::milliseconds>(std::get<0>(ret)).count() <<
" milliseconds." << std::endl;
std::cout << "function returned: " << std::get<1>(ret) << std::endl;
假设auto ret = countTime(&Test::init, *this, 1, 1.2);
int value = std::get<1>(ret);
std::cout << std::chrono::duration_cast<std::chrono::milliseconds>(std::get<0>(ret)).count() << "ms" << std::endl;
函数,一个简单的示例调用:
int init(int, int)
可通过onlinegdb获得实时版本。