游戏服务器之性能统计
发表于2018-04-22
性能统计分析器用来统计多个函数在一定执行次数下的执行时间,并输出函数执行时间较长的函数名和时间。
(1)性能统计分析器
class Performance_Statistics { private: struct Performance { Performance():_times(0),_total_time(0) {} /** * \author: cjy * \description: 执行的次数 */ unsigned long _times; /** * \author: cjy * \description:执行的总时间 */ unsigned long _total_time; }; std::map<std::string, Performance> _times; timer _log_timer; public: Performance_Statistics(const int how_long) : _log_timer(how_long) {} ~Performance_Statistics() {} void inc(const std::string &func, const unsigned long total) { Performance &mt = _times[func]; if (mt._times) { ++mt._times; mt._total_time += total; } else { ++mt._times; mt._total_time = total; } } void reset(const realtime &ct, const bool force_print) { if (force_print || _log_timer(ct)) { g_log->debug("[分时统计]:%s, %lu", force_print ? "force" : "timer", _times.size()); for(std::map<std::string, Performance>::iterator it = _times.begin(); it != _times.end(); ++it) { if (it->second._times && (it->second._total_time / 1000000L) > 5)//输出5ms以上的 { g_log->debug("[分时统计]:%s, %lu毫秒, %lu次, %lu毫秒/次",it->first.c_str(), it->second._total_time /1000000L, it->second._times, (it->second._total_time / 1000000L) / it->second._times); } } } _times.clear(); } };
(2)统计方便函数,在构造函数和析构函数里执行时间统计
class Function_Exe_Time { private: const std::string _func; struct timespec _tv_1; public: static Performance_Statistics my_func; Function_Exe_Time(const std::string &func) : _func(func) { clock_gettime(CLOCK_REALTIME, &_tv_1); } ~Function_Exe_Time() { struct timespec _tv_2; clock_gettime(CLOCK_REALTIME, &_tv_2); unsigned long end=(unsigned long)_tv_2.tv_sec*1000000000L + _tv_2.tv_nsec; unsigned long begin=(unsigned long)_tv_1.tv_sec*1000000000L + _tv_1.tv_nsec; my_func.inc(_func, end-begin); } };
(3)定时器
/** * \author cjy * \description 定时器 * 固定时间间隔的定时器,方便对于时间间隔的判断,精确到毫秒级 */ class timer { public: /** * \author cjy * \description构造函数 * \param how_long 定时器的时间,单位:毫秒 * \param first 有些定时器可能希望在启动时就可以执行一次,所以不能直接addDelay哦 */ explicit timer(const int64 how_long, bool first=false, const int64 delay=0) : _long(how_long), _timer() { if(!first) _timer.addDelay(_long+delay); } /** * \author cjy * \description构造函数 * \param how_long 定时器的时间,单位:毫秒 * \param first 有些定时器可能希望在启动时就可以执行一次,所以不能直接addDelay哦 * \param ctv 当前时间 */ explicit timer(const int64 how_long, bool first , realtime &ctv) : _long(how_long), _timer(ctv) { if(!first) _timer.addDelay(_long); } /** * \author cjy * \description重新设置定时器的精度和开始计时时间 * \param how_long 定时器的时间,单位:毫秒 * \param ctv 当前时间 */ void reset(const uint64 how_long, const realtime &cur) { _long = how_long; _timer = cur; _timer.addDelay(_long); } /** * \author cjy * \description重新设置定时器的时间 * \param cur 指定定时器启动的时间 */ void current(const realtime &cur) { _timer = cur; } /** * \author cjy * \description延时定时器时间 * \param cur 指定定时器启动的时间 * \param delay 延时时间 */ void next(const realtime &cur, const uint32 delay) { _timer = cur; _timer.addDelay(delay); } /** * \author cjy * \description重新设置定时器的时间 * \param cur 指定定时器启动的时间 */ void next(const realtime &cur) { _timer = cur; _timer.addDelay(_long); } /** * \author cjy * \description倒计时剩余秒数.不受时间调整影响. * \param cur 当前时间 * return 剩余描述 */ inline uint32 leftSec(const realtime &cur) { return (_timer.sec() > cur.sec()) ? (_timer.sec() - cur.sec()) : 0; } /** * \author cjy * \description倒计时剩余毫秒数.受时间调整影响 * \param cur 当前时间 * return 剩余值 */ inline uint64 leftMSec(const realtime &cur) { return (_timer._msec > cur._msec) ? (_timer._msec - cur._msec) : 0; } /** * \author cjy * \description定时器检查 * \param cur 检查定时器的时间 * return 是否到达指定时间 */ inline bool operator() (const realtime &cur) { if (_timer._msec > cur._msec) { return false; } addDelay(cur); return true; } inline void addDelay(uint64 addLong)//添加延迟 { _timer.addDelay(addLong); } private: /** * \author cjy * \description定时器时间间隔 */ uint64 _long; /** * \author cjy * \description上次检查定时器的时间 */ realtime _timer; private: /** * \author cjy * \description非严格检测,存在积累误差 * 从效率方面考虑,严格监测定时器的需求并不是必须的,去除对严格监测的支持 */ inline void addDelay(const realtime& cur) { _timer = cur; _timer.addDelay(_long); } };
(4)测试实例
测试ai攻击处理花费时间
{ Function_Exe_Time func("NPC_AI_ATTACK"STR(__LINE__)); return doAttackAI(); }
来自:https://blog.csdn.net/chenjiayi_yun/article/details/35276861