AIX下C/C++函数性能统计实现方法--改进版
发表于:2025-02-05 作者:千家信息网编辑
千家信息网最后更新 2025年02月05日,上一篇实现,是统计了每一次函数调用的层次关系和耗时。如果在函数调用比较多的情况下,更关心的是减少输出,只需要总计的耗时即可。另外如果是后台程序,输出到文件会更好。因此,对程序做了改进。当设置TRACE
千家信息网最后更新 2025年02月05日AIX下C/C++函数性能统计实现方法--改进版#include <iostream>
#include <fstream>
#include <vector>
#include <map>
#include <string>
#include <sys/time.h>
using std::vector;
using std::map;
using std::string;
using std::clog;
using std::endl;
using std::ofstream;
using std::ostream;
extern "C" void print_trace(const char * const procname);
struct Stat
{
int lvl;
string name;
long stm;
long etm;
long oitv;
Stat(int l, const string& s, long st) : lvl(l), name(s), stm(st), etm(0), oitv(0) {}
};
struct Sum
{
int cnt;
long itv;
Sum() : cnt(0), itv(0) {}
Sum operator+=(long i)
{
++cnt;
itv+=i;
return *this;
}
};
namespace
{
vector<Stat> tracev;
map<string, Sum> itvm;
int clvl = 0;
bool detailf = (getenv("DETAILF")!=NULL);
}
extern "C" void
__func_trace_enter(const char * const proc_name,
const char * const file_name,
const int line_no,
void ** const id)
{
// printf("{ %s (%s:%d) %p %s\n", proc_name, file_name, line_no, id[0], (char*)*id);
struct timeval nowtm;
gettimeofday(&nowtm, NULL);
++clvl;
tracev.push_back(Stat(clvl, string(proc_name)+"() : "+file_name, nowtm.tv_sec * 1000000 + nowtm.tv_usec));
}
extern "C" void
__func_trace_exit(const char * const proc_name,
const char * const file_name,
const int line_no,
void ** const id)
{
// printf("} %s (%s:%d) %p %s\n", proc_name, file_name, line_no, id[0], (char*)*id);
struct timeval nowtm;
int itv;
gettimeofday(&nowtm, NULL);
auto iter = tracev.end() - 1;
while (iter->etm != 0)
--iter;
iter->etm = nowtm.tv_sec * 1000000 + nowtm.tv_usec;
itv = iter->etm - iter->stm - iter->oitv;
itvm[proc_name]+=itv;
for (auto s = tracev.begin(); s!=iter; ++s)
{
if (s->etm == 0)
s->oitv += itv;
}
--clvl;
if (!detailf)
tracev.erase(iter, tracev.end());
if (clvl == 0)
{
print_trace(proc_name);
tracev.clear(); itvm.clear(); }
}
extern "C" void print_trace(const char * const procname)
{
time_t t;
char buf[30];
ofstream logf(getenv("TRACELOG"), std::ios::app);
ostream &log = logf ? logf : clog;
if (detailf)
{
log<<"Detail of "<< procname <<"() :\n";
for (auto s = tracev.begin(); s!=tracev.end(); ++s)
{
log << s->lvl << "\t";
t=s->stm/1000000;
strftime(buf, sizeof(buf), "%Y%m%d%H%M%S", localtime(&t));
log << buf << "." << s->stm % 1000000 << "\t";
t=s->etm/1000000;
strftime(buf, sizeof(buf), "%Y%m%d%H%M%S", localtime(&t));
log << buf << "." << s->etm % 1000000 << "\t";
log << s->etm-s->stm << "\t" << s->oitv << "\t" << s->etm-s->stm-s->oitv << "\t";
log << string(s->lvl-1, ' ') << s->name << "\n";
}
}
log<<"Total of "<< procname <<"() :\n";
for (auto s = itvm.begin(); s!=itvm.end(); ++s)
{
log << s->first << "()\t count "<< (s->second).cnt << "\ttime " << (s->second).itv << "\n";
}
log<<endl;
}
上一篇实现,是统计了每一次函数调用的层次关系和耗时。如果在函数调用比较多的情况下,更关心的是减少输出,只需要总计的耗时即可。另外如果是后台程序,输出到文件会更好。
因此,对程序做了改进。当设置TRACELOG环境变量,则输出到这个环境变量指定的文件中。如果设置了DETAILF,则会输出调用层次关系和每一次的耗时,否则只输出总计时间。
tr.cpp改进后的程序如下。
设置DETAILF后,运行后输出结果如下。
Detail of main() :
1 20170801152000.103879 20170801152000.104034 155 58 97 main() : tt.c
2 20170801152000.103954 20170801152000.103997 43 3 40 f1() : tt.c
3 20170801152000.103958 20170801152000.103961 3 0 3 f2() : tt.c
2 20170801152000.104017 20170801152000.104032 15 3 12 f1() : tt.c
3 20170801152000.104021 20170801152000.104024 3 0 3 f2() : tt.c
Total of main() :
f1() count 2 time 0.000052 s
f2() count 2 time 0.000006 s
main() count 1 time 0.000097 s
输出
程序
变量
层次
文件
环境
函数
统计
一次函数
后台
情况
时间
结果
上一
运行
性能
方法
数据库的安全要保护哪些东西
数据库安全各自的含义是什么
生产安全数据库录入
数据库的安全性及管理
数据库安全策略包含哪些
海淀数据库安全审计系统
建立农村房屋安全信息数据库
易用的数据库客户端支持安全管理
连接数据库失败ssl安全错误
数据库的锁怎样保障安全
新野app软件开发
望城比亚迪软件开发双休吗
外网远程连接服务器
阿里自己的数据库
数据库升级后再联机
一个数据库可以有几个外模
用友t3数据库输入密码
其他网络安全性
临沂方位网络技术有限公司介绍
智慧树知到数据库技术答案
vr端软件开发公司
保定市网络安全服务人员
孤岛惊魂6钻井平台服务器机房
水利系统网络安全使用制度
软件开发平台协议
提升数据库能力
吉利汽车功能研发部软件开发
天门招网络安全工程师吗
光学数据库不学编程可以么
服务器抢免费
数据库管理系统分层体系
期刊数据库泄露抢发
山西质量软件开发
三亚直播软件开发大概多少钱
幻塔红石柱服务器是哪些平台的
软件开发南京大学
上海计算机网络技术及应用
全球网络安全国家
更改数据库名字语句
网络安全国旗下演讲图片