C ++使用std :: chrono很好地衡量成员函数的执行情况

时间:2018-10-20 12:58:33

标签: c++ time std chrono

我想优化我的应用程序,尤其是某些功能的执行速度。

想象有一个带有一些成员函数的类

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);

3 个答案:

答案 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获得实时版本。