c++ - 快速而肮脏的方式来分析你的代码

标签 c++ performance profiling code-snippets

当您想获取有关特定代码路径的性能数据时,您使用什么方法?

最佳答案

这种方法有一些局限性,但我仍然觉得它非常有用。我会预先列出限制(我知道),让任何想要使用它的人自行承担风险。

  1. 我发布的原始版本夸大了递归调用所花费的时间(正如答案的评论中所指出的那样)。
  2. 它不是线程安全的,在我添加代码以忽略递归之前它不是线程安全的,现在它的线程安全性更差了。
  3. 虽然调用多次(数百万次)会非常有效,但它会对结果产生可衡量的影响,因此您测量的范围将比您不测量的范围花费更长的时间。

当手头的问题不能证明分析我的所有代码是合理的,或者我从分析器获得一些我想要验证的数据时,我会使用这个类。基本上它总结了您在特定 block 中花费的时间,并在程序结束时将其输出到调试流(可通过 DbgView 查看),包括代码执行的次数(当然还有平均花费的时间) )。

#pragma once
#include <tchar.h>
#include <windows.h>
#include <sstream>
#include <boost/noncopyable.hpp>

namespace scope_timer {
    class time_collector : boost::noncopyable {
        __int64 total;
        LARGE_INTEGER start;
        size_t times;
        const TCHAR* name;

        double cpu_frequency()
        { // cache the CPU frequency, which doesn't change.
            static double ret = 0; // store as double so devision later on is floating point and not truncating
            if (ret == 0) {
                LARGE_INTEGER freq;
                QueryPerformanceFrequency(&freq);
                ret = static_cast<double>(freq.QuadPart);
            }
            return ret;
        }
        bool in_use;

    public:
        time_collector(const TCHAR* n)
            : times(0)
            , name(n)
            , total(0)
            , start(LARGE_INTEGER())
            , in_use(false)
        {
        }

        ~time_collector()
        {
            std::basic_ostringstream<TCHAR> msg;
            msg << _T("scope_timer> ") <<  name << _T(" called: ");

            double seconds = total / cpu_frequency();
            double average = seconds / times;

            msg << times << _T(" times total time: ") << seconds << _T(" seconds  ")
                << _T(" (avg ") << average <<_T(")\n");
            OutputDebugString(msg.str().c_str());
        }

        void add_time(__int64 ticks)
        {
            total += ticks;
            ++times;
            in_use = false;
        }

        bool aquire()
        {
            if (in_use)
                return false;
            in_use = true;
            return true;
        }
    };

    class one_time : boost::noncopyable {
        LARGE_INTEGER start;
        time_collector* collector;
    public:
        one_time(time_collector& tc)
        {
            if (tc.aquire()) {
                collector = &tc;
                QueryPerformanceCounter(&start);
            }
            else
                collector = 0;
        }

        ~one_time()
        {
            if (collector) {
                LARGE_INTEGER end;
                QueryPerformanceCounter(&end);
                collector->add_time(end.QuadPart - start.QuadPart);
            }
        }
    };
}

// Usage TIME_THIS_SCOPE(XX); where XX is a C variable name (can begin with a number)
#define TIME_THIS_SCOPE(name) \
    static scope_timer::time_collector st_time_collector_##name(_T(#name)); \
    scope_timer::one_time st_one_time_##name(st_time_collector_##name)

关于c++ - 快速而肮脏的方式来分析你的代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61278/

相关文章:

java - 用于分析大型 Java 堆转储的工具

C++ 真正基础的绘图/GUI

c++ - 将存储在int中的内存地址分配给int

sql - 使用 SQL INNER JOIN 有什么不好

sql-server - Linq to SQL 性能与分组

jakarta-ee - 在 tomcat 上跟踪/分析应用程序

c++ - 使用双指针在链表中插入一个节点

c++ - 具有同名抽象和定义继承函数的多重继承

database - 什么指标可以高效地应用于这种情况?

profiling - 仪器分析 : "top functions" reorders functions