溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶(hù)服務(wù)條款》

AIX下C/C++函數(shù)性能統(tǒng)計(jì)實(shí)現(xiàn)方法

發(fā)布時(shí)間:2020-08-09 10:27:37 來(lái)源:ITPUB博客 閱讀:167 作者:pacman2000 欄目:建站服務(wù)器

在AIX中,xlc編譯器有個(gè)選項(xiàng)-qfunctrace,使用此選項(xiàng)編譯的程序,自動(dòng)會(huì)在每個(gè)函數(shù)的入口出口處調(diào)用以下自定義函數(shù)。


extern "C" void
__func_trace_enter(const char * const proc_name,
                   const char * const file_name,
                   const int line_no,
                   void ** const id);


extern "C" void
__func_trace_exit(const char * const proc_name,
                   const char * const file_name,
                   const int line_no,
                   void ** const id);


extern "C" void
__func_trace_catch(const char * const proc_name,
                   const char * const file_name,
                   const int line_no,
                   void ** const id);


在函數(shù)調(diào)用前,執(zhí)行__func_trace_enter(),函數(shù)正常返回后,執(zhí)行__func_trace_exit()。如果函數(shù)是通過(guò)throw異常拋出的,那么在異常被catch捕獲處,執(zhí)行__func_trace_catch(),但是遇到catch(...)捕獲不會(huì)執(zhí)行。值得注意的是,如果時(shí)throw拋出,不會(huì)觸發(fā)__func_trace_exit()。


使用這個(gè)功能,可以實(shí)現(xiàn)無(wú)需修改源程序,進(jìn)行性能統(tǒng)計(jì)的效果。程序如下。


tr.cpp為自定義函數(shù)出入口程序,每個(gè)函數(shù)執(zhí)行時(shí)都會(huì)經(jīng)過(guò)。編譯成為libfunctr.so。

  • #include <iostream>
  • #include <vector>
  • #include <string>
  • #include <sys/time.h>

  • using std::vector;
  • using std::string;
  • using std::clog;
  • using std::endl;

  • extern "C" void print_trace();

  • 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) {}
  • };

  • static vector<Stat> tracev;
  • static int clvl = 0;

  • 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;
  •     for (auto s = tracev.begin(); s!=tracev.end(); s++)
  •     {
  •         if (s->etm == 0)
  •             s->oitv += itv;
  •     }
  •     --clvl;
  •     if (clvl == 0)
  •         print_trace();
  • }

  • extern "C" void print_trace()
  • {
  •     time_t t;
  •     char buf[30];
  •     for (auto s = tracev.begin(); s!=tracev.end(); s++)
  •     {
  •         clog << s->lvl << "\t";
  •         t=s->stm/1000000;
  •         strftime(buf, sizeof(buf), "%Y%m%d%H%M%S", localtime(&t));
  •         clog << buf << "." << s->stm % 1000000 << "\t";
  •         t=s->etm/1000000;
  •         strftime(buf, sizeof(buf), "%Y%m%d%H%M%S", localtime(&t));
  •         clog << buf << "." << s->etm % 1000000 << "\t";
  •         clog << s->etm-s->stm << "\t" << s->oitv << "\t" << s->etm-s->stm-s->oitv << "\t";
  •         clog << string(s->lvl-1, ' ') << s->name << endl;
  •     }
  • }


  • tt.c為演示的例子程序。編譯成可執(zhí)行文件tt。

  • #include <stdio.h>

  • int f2(int i)
  • {
  •     return i*2;
  • }

  • int f1(int i)
  • {
  •     return f2(i+1);
  • }

  • int main(int argc, char **argv)
  • {
  •         for (int i=0;i<2;i++)
  •             f1(i);
  • }


  • makefile為把tr.cpp編譯成so庫(kù),給tt.c連接使用(不修改tt.c任何代碼)。注意編譯tt.c時(shí)使用了-qfunctrace和-lC。

  • all:
  • xlC -bnoentry -G -o libfunctr.so -qlanglvl=extended0x tr.cpp
  • chmod go-rwx libfunctr.so
  • xlc -bdynamic -brtl -qfunctrace -o tt tt.c -L. -lfunctr -lC


  • 執(zhí)行后,效果如下:
    $tt
    1       20170429170216.354105   20170429170216.354151   46      27      19      main() : tt.c
    2       20170429170216.354123   20170429170216.354137   14      6       8        f1() : tt.c
    3       20170429170216.354130   20170429170216.354136   6       0       6         f2() : tt.c
    2       20170429170216.354138   20170429170216.354151   13      6       7        f1() : tt.c
    3       20170429170216.354144   20170429170216.354150   6       0       6         f2() : tt.c

    分別表示:函數(shù)的層次,開(kāi)始時(shí)間,結(jié)束時(shí)間,總耗時(shí)(包含嵌套調(diào)用),嵌套調(diào)用其他函數(shù)總耗時(shí),函數(shù)自身代碼耗時(shí),函數(shù)名和源文件名。

    向AI問(wèn)一下細(xì)節(jié)

    免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

    AI