在类实例或方法的上下文中调用函数以进行性能分析

Invoke a function in context of a class instance or method for performance analysis

本文关键字:函数 性能 调用 实例 方法 上下文      更新时间:2023-10-16

性能分析问题:有没有办法在类的上下文或类的方法中执行函数?

我想分析特定逻辑段的性能。我设想的是这样的

(免责声明:粗略的例子只是为了说明一点。不会编译(。

const int DEBUG_LEVEL = 7;
class PerfWrapper {
public:
    PerfWrapper(int f) {} // Constructor: take function as argument
    void invoke() {} // Invoke the function passed as argument
    double execution_time() {
        begin = std::chrono::high_resolution_clock::now();
        // etc..
    } 
    double memory_usage() {}
private:
}
int foo() {
    int sum{0}
    for (int i=0; i<1000; ++i)
        for (int j=0; j<MAX; ++j) 
            sum += i * j;
    return sum;
}
int main() {
    if (DEBUG_LEVEL = 7)
        PerfWrapper p(foo); // Create an instance, passing foo as an argument
        // below foo() is called in context of the performance wrapper
        int myTime = p.invoke().execution_time(); // Invokes foo in context of p and tracks execution time
        int myMemory = p.invoke().memory_usage(); // Same, except gathering memory usage info.
        // etc..
    }
}

这里我们有类PerfWrapper。实例化后,对象上的结果方法能够接受函数作为参数,并在类的上下文中执行函数。它将进行性能测量,其结果可通过界面访问。

请注意"DEBUG_LEVEL"设置。如果需要性能分析,则只需将DEBUG_LEVEL设置为 7。

你见过这样的东西吗?如果没有,如何最好地完成分析?我知道它似乎有点离谱,但希望不是那么多。谢谢,基思:^(

也许您正在寻找函数指针,可以使用这些指针,如以下简化代码所示:

typedef int(*aFooFunctionType)(void);
class PerformanceTest {
public:
    PerformanceTest(aFooFunctionType fooFuncPtr) { m_fooFuncPtr = fooFuncPtr; }
    void test() {
        int x = m_fooFuncPtr();
        // do something with x (or not...)
    };
private:
    aFooFunctionType m_fooFuncPtr;
};

int fooFunc(void) {
    return 100;
}
int main(int argc, char* argv[]) {
    PerformanceTest pTest(fooFunc);
    pTest.test();
    return 0;
}
<</div> div class="answers">

您几乎可以将任何东西包装在std::function中。我建议在PerfWrapper中使用std::function来获取执行时间。不过,我没有任何东西可以测量内存使用情况。

示例代码:

#include <iostream>
#include <functional>
#include <chrono>
class PerfWrapper
{
   public:
      PerfWrapper(std::function<void()> f) : f_(f), execution_time_{} {}
      void invoke()
      {
         auto begin = std::chrono::high_resolution_clock::now();
         f_();
         auto end = std::chrono::high_resolution_clock::now();
         execution_time_ = end-begin;
      }
      double execution_time()
      {
         return execution_time_.count();
      } 
      std::function<void()> f_;
      std::chrono::duration<double> execution_time_;
};
unsigned long foo()
{
   unsigned long sum{0};
   for (int i=0; i<10000; ++i)
      for (int j=0; j<2000; ++j) 
         sum += i * j;
   return sum;
}
int main()
{
   PerfWrapper pr([](){std::cout << foo() << std::endl;});
   pr.invoke();
   std::cout << "Execution time: " << pr.execution_time() << std::endl;
}

我的设置上的输出:

99940005000000
Execution time: 0.0454077

考虑使用无模板函数,并使用引用参数来提取性能数据。 此示例将:

  • 接受函数指针和函子(包括std::function,这意味着它也可以与方法一起使用(。
  • 返回与代理函数调用返回的值相同的值,因此您可以同时使用测量数据和调用结果。

struct measurement {
    double execution_time;
    double memory_usage;
};
template <typename FN, typename... T>
inline auto measure(FN fn, measurement& m, T&&... args) -> decltype(fn(std::forward<T>(args)...))
{
    auto&& result = fn(std::forward<T>(args)...);
    m.execution_time = 0; // example
    m.memory_usage = 0;
    return result;
}