AIX下C/C++函数性能统计实现方法--改进版
发表于:2025-12-03 作者:千家信息网编辑
千家信息网最后更新 2025年12月03日,上一篇实现,是统计了每一次函数调用的层次关系和耗时。如果在函数调用比较多的情况下,更关心的是减少输出,只需要总计的耗时即可。另外如果是后台程序,输出到文件会更好。因此,对程序做了改进。当设置TRACE
千家信息网最后更新 2025年12月03日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安全错误
数据库的锁怎样保障安全
清华大学网络安全专业就业方向
2022单招网络技术女生多吗
软件开发烂尾人物
firedatabase数据库
对基层网络安全进行检查
全英软件开发岗
杭州边锋网络技术有限公司开
维普数据库怎么查找老师发表论文
wpf读取数据库生成表格
服务器主板跳线插图片
唐河县天气预报软件开发
数据库技术大会2016
软件开发ppt主题
一个服务器可以同时训练多个模型
网络安全与执法要学枪械
安徽益美丽家网络技术有限公司
教师网络技术培训的好处
极客湾数据库在哪看
数据库更新当前时间语句
南昌市学网络技术的学校
厦门联想服务器维修站
数据库如何理解关系
欧莱雅数据库工程师
阿里云香港轻量服务器双11优惠
王者服务器怎么炸的
数据库实训个人总结
数据库更新当前时间语句
多用户商城数据库设计
数据库清洗函数
如何清理软件数据库缓存