快速和肮脏的方式来配置您的代码 [英] Quick and dirty way to profile your code

查看:191
本文介绍了快速和肮脏的方式来配置您的代码的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

解决方案

,但我还是觉得很有用。我会列出前面的限制(我知道),让任何人想要使用它自己的风险。


  1. 原始版本我发布了超过报告的时间花费在递归调用(如在回答的评论中指出的)。

  2. 它不是线程安全的,它不是线程安全,

  3. 虽然如果它被调用多次(百万),它是非常有效的,但它对结果有一个可测量的影响,以便您测量的范围





  4. 我使用这个类,当问题在手边没有证据分析我的所有代码或我从我想要验证的分析器获得一些数据。基本上,它总结了你在特定块中花费的时间,并在程序结束时将其输出到调试流(可通过 DbgView ),包括执行代码的次数(和平均花费的时间))。

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

    命名空间scope_timer {
    class time_collector:boost :: noncopyable {
    __int64 total;
    LARGE_INTEGER start;
    size_t times;
    const TCHAR * name;

    double cpu_frequency()
    {//缓存CPU频率,不会改变。
    static double ret = 0; // store as double so devision later is is float 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>)<<名称<< _T(called:);

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

    msg<< times<< _T(times total time:)<秒< _T(seconds)
    << _T((avg));
    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);
    }
    }
    };
    }

    //用法TIME_THIS_SCOPE(XX);其中XX是一个C变量名(可以以数字开头)
    #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)


    What method do you use when you want to get performance data about specific code paths?

    解决方案

    This method has several limitations, but I still find it very useful. I'll list the limitations (I know of) up front and let whoever wants to use it do so at their own risk.

    1. The original version I posted over-reported time spent in recursive calls (as pointed out in the comments to the answer).
    2. It's not thread safe, it wasn't thread safe before I added the code to ignore recursion and it's even less thread safe now.
    3. Although it's very efficient if it's called many times (millions), it will have a measurable effect on the outcome so that scopes you measure will take longer than those you don't.


    I use this class when the problem at hand doesn't justify profiling all my code or I get some data from a profiler that I want to verify. Basically it sums up the time you spent in a specific block and at the end of the program outputs it to the debug stream (viewable with DbgView), including how many times the code was executed (and the average time spent of course)).

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

    这篇关于快速和肮脏的方式来配置您的代码的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆