CMS 3D CMS Logo

IgProf Class Reference

Core profiling implementation. More...

#include <IgTools/IgProf/src/IgProf.h>

List of all members.

Static Public Member Functions

static IgProfTracebuffer (int moduleid)
 Return a profile buffer for a profiler in the current thread.
static void debug (const char *format,...)
 Internal printf()-like debugging utility.
static bool disable (bool globally)
 Disable the profiling system, either globally or just in this thread.
static void dump (void)
 Dump out the profiler data: trace tree and live maps.
static bool enable (bool globally)
 Enable the profiling system, either globally or just in this thread.
static bool enabled (bool globally)
 Check if the profiler is currently enabled.
static void exitThread (bool final)
 Finalise a thread.
static bool initialize (int *moduleid, void(*threadinit)(void), bool perthread)
 Initialise the profiler core itself.
static void initThread (void)
 Setup a thread so it can be used in profiling.
static bool isMultiThreaded (void)
 Return true if the process was linked against threading package.
static const char * options (void)
 Get user-provided profiling options.
static int panic (const char *file, int line, const char *func, const char *expr)
 Internal assertion helper routine.


Detailed Description

Core profiling implementation.

Implements utilities needed to implement actual profiler modules as well as final dumps.

Definition at line 11 of file IgProf.h.


Member Function Documentation

IgProfTrace * IgProf::buffer ( int  moduleid  )  [static]

Return a profile buffer for a profiler in the current thread.

It is safe to call this function from any thread and in asynchronous signal handlers at any time. Returns the buffer to use or a null to indicate no data should be gathered in the calling context, for example if the profile core itself has already been destroyed.

Definition at line 315 of file IgProf.cc.

References IgProfTraceAlloc::buf, s_activated, s_bufkey, s_bufs, s_mainthread, and thread.

Referenced by __attribute__(), profileSignalHandler(), and remove().

00316 {
00317   // Check which pool to return.  We return the one from s_bufs in
00318   // non-threaded applications and always in the main thread.  In
00319   // other threads we return the main thread buffer if a single buffer
00320   // was requested, otherwise a per-thread buffer.
00321   pthread_t thread = pthread_self();
00322   IgProfTraceAlloc *bufs = s_bufs;
00323   if (! s_activated)
00324     bufs = 0;
00325   else if (thread != s_mainthread && s_bufs[moduleid].perthread)
00326     bufs = (IgProfTraceAlloc *) pthread_getspecific(s_bufkey);
00327 
00328   return bufs ? bufs[moduleid].buf : 0;
00329 }

void IgProf::debug ( const char *  format,
  ... 
) [static]

Internal printf()-like debugging utility.

Produces output if $IGPROF_DEBUGGING environment variable is set to any value.

Definition at line 423 of file IgProf.cc.

References e.

Referenced by IgProfTrace::acquireResource(), IgProfBuffer::allocateRaw(), doexit(), dokill(), dopthread_sigmask(), dosigaction(), dump(), initialize(), initialize(), threadWrapper(), and IgProfExitDump::~IgProfExitDump().

00424 {
00425   static const char *debugging = getenv("IGPROF_DEBUGGING");
00426   if (debugging)
00427   {
00428     timeval tv;
00429     gettimeofday(&tv, 0);
00430     fprintf(stderr, "*** IgProf(%lu, %.3f): ",
00431             (unsigned long) getpid(),
00432             tv.tv_sec + 1e-6*tv.tv_usec);
00433 
00434     va_list args;
00435     va_start(args, format);
00436     vfprintf(stderr, format, args);
00437     va_end(args);
00438   }
00439 }

bool IgProf::disable ( bool  globally  )  [static]

Disable the profiling system, either globally or just in this thread.

This is safe to call from anywhere. Returns true if the profiler was enabled before the call.

Definition at line 370 of file IgProf.cc.

References IgProfAtomicDec(), s_enabled, s_flagkey, and s_pthreads.

Referenced by doaccept(), doclose(), dodup(), dodup2(), doexit(), dokill(), doopen(), doopen64(), dopthread_create(), dosocket(), initialize(), initialize(), panic(), and IgProfExitDump::~IgProfExitDump().

00371 {
00372   if (! globally && s_pthreads)
00373   {
00374     IgProfAtomic *flag = (IgProfAtomic *) pthread_getspecific(s_flagkey);
00375     return flag ? (IgProfAtomicDec(flag) >= 0 && s_enabled > 0) : false;
00376   }
00377   else
00378   {
00379     IgProfAtomic newval = IgProfAtomicDec(&s_enabled);
00380     return newval >= 0;
00381   }
00382 }

void IgProf::dump ( void   )  [static]

Dump out the profiler data: trace tree and live maps.

Definition at line 502 of file IgProf.cc.

References debug(), dumpProfile(), info, output(), s_clockres, s_masterbuf, s_outname, and IgProfTrace::stackRoot().

Referenced by dokill(), and IgProfExitDump::~IgProfExitDump().

00503 {
00504   static bool dumping = false;
00505   if (dumping) return;
00506   dumping = true;
00507 
00508   FILE *output = (s_outname[0] == '|'
00509                   ? (unsetenv("LD_PRELOAD"), popen(s_outname+1, "w"))
00510                   : fopen (s_outname, "w+"));
00511   if (! output)
00512   {
00513     IgProf::debug("can't write to output %s: %d\n", s_outname, errno);
00514     dumping = false;
00515     return;
00516   }
00517 
00518   IgProfDumpInfo info = { 0, 0, 0, 0 };
00519   IgProf::debug("dumping state to %s\n", s_outname);
00520   fprintf(output, "P=(ID=%lu N=(%s) T=%f)\n",
00521           (unsigned long) getpid(), program_invocation_name, s_clockres);
00522   dumpProfile(output, s_masterbuf->stackRoot(), info);
00523   fclose(output);
00524   dumping = false;
00525 }

bool IgProf::enable ( bool  globally  )  [static]

Enable the profiling system, either globally or just in this thread.

This is safe to call from anywhere. Returns true if the profiler is enabled after the call.

Definition at line 352 of file IgProf.cc.

References IgProfAtomicInc(), s_enabled, s_flagkey, and s_pthreads.

Referenced by doaccept(), doclose(), dodup(), dodup2(), doexit(), dokill(), doopen(), doopen64(), dopthread_create(), dosocket(), initialize(), and initialize().

00353 {
00354   if (! globally && s_pthreads)
00355   {
00356     IgProfAtomic *flag = (IgProfAtomic *) pthread_getspecific(s_flagkey);
00357     return flag ? (IgProfAtomicInc(flag) > 0 && s_enabled > 0) : false;
00358   }
00359   else
00360   {
00361     IgProfAtomic newval = IgProfAtomicInc(&s_enabled);
00362     return newval > 0;
00363   }
00364 }

bool IgProf::enabled ( bool  globally  )  [static]

Check if the profiler is currently enabled.

This function should be called by asynchronous signal handlers to check whether they should record profile data -- not for the actual running where the value of the flag has little useful value, but to make sure no data is gathered after the system has started to close down.

Definition at line 337 of file IgProf.cc.

References s_enabled, s_flagkey, and s_pthreads.

Referenced by dokill(), initThread(), and profileSignalHandler().

00338 {
00339   if (! globally && s_pthreads)
00340   {
00341     IgProfAtomic *flag = (IgProfAtomic *) pthread_getspecific(s_flagkey);
00342     return flag ? (*flag > 0 && s_enabled > 0) : false;
00343   }
00344   else
00345     return s_enabled > 0;
00346 }

void IgProf::exitThread ( bool  final  )  [static]

Finalise a thread.

Definition at line 280 of file IgProf.cc.

References i, IgProfTrace::mergeFrom(), N_MODULES, p, s_bufkey, s_bufs, s_mainthread, s_masterbuf, s_pthreads, and thread.

Referenced by doexit(), threadWrapper(), and IgProfExitDump::~IgProfExitDump().

00281 {
00282   if (! s_pthreads && ! final)
00283     return;
00284 
00285   pthread_t thread = pthread_self ();
00286   IgProfTraceAlloc *bufs
00287     = (thread == s_mainthread ? s_bufs
00288        : (IgProfTraceAlloc *) pthread_getspecific(s_bufkey));
00289 
00290   for (int i = 0; i < N_MODULES && bufs; ++i)
00291   {
00292     IgProfTrace *p = bufs[i].buf;
00293     if (p)
00294     {
00295       s_masterbuf->mergeFrom(*p);
00296       bufs[i].buf = 0;
00297       delete p;
00298     }
00299   }
00300 
00301   if (thread == s_mainthread)
00302     s_bufs = 0;
00303   else
00304     pthread_setspecific(s_bufkey, 0);
00305 
00306   delete [] bufs;
00307 }

bool IgProf::initialize ( int moduleid,
void(*)(void threadinit,
bool  perthread 
) [static]

Initialise the profiler core itself.

Prepares the the program for profiling. Captures various exit points so we generate a dump before the program goes "out". Automatically triggered to run on library load. All profiler modules should invoke this method before doing their own initialisation.

Returns true if profiling is activated in this process.

Definition at line 115 of file IgProf.cc.

References debug(), disable(), e, enable(), IgHook::hook(), i, initBuf(), MAX_FNAME, N_MODULES, options(), IgProfTrace::OptResources, bookConverter::opts, s_activated, s_bufkey, s_bufs, s_clockres, s_dumpflag, s_enabled, s_flagkey, s_initialized, s_mainthread, s_masterbuf, s_masterbufdata, s_outname, s_pthreads, s_symcache, s_symcachedata, target, and threadinits().

Referenced by initialize().

00116 {
00117   if (! s_initialized)
00118   {
00119     s_initialized = true;
00120 
00121     const char *options = IgProf::options();
00122     if (! options || ! *options)
00123     {
00124       IgProf::debug("$IGPROF not set, not profiling this process\n");
00125       return s_activated = false;
00126     }
00127 
00128     for (const char *opts = options; *opts; )
00129     {
00130       while (*opts == ' ' || *opts == ',')
00131         ++opts;
00132 
00133       if (! strncmp(opts, "igprof:out='", 12))
00134       {
00135         int i = 0;
00136         opts += 12;
00137         while (i < MAX_FNAME-1 && *opts && *opts != '\'')
00138           s_outname[i++] = *opts++;
00139         s_outname[i] = 0;
00140       }
00141       else if (! strncmp(opts, "igprof:dump='", 13))
00142       {
00143         int i = 0;
00144         opts += 13;
00145         while (i < MAX_FNAME-1 && *opts && *opts != '\'')
00146           s_dumpflag[i++] = *opts++;
00147         s_dumpflag[i] = 0;
00148       }
00149       else
00150         opts++;
00151 
00152       while (*opts && *opts != ',' && *opts != ' ')
00153         opts++;
00154     }
00155 
00156     if (! s_outname[0])
00157       sprintf(s_outname, "igprof.%ld", (long) getpid());
00158 
00159     s_bufs = new IgProfTraceAlloc[N_MODULES];
00160     memset(s_bufs, 0, N_MODULES * sizeof(*s_bufs));
00161 
00162     void *program = dlopen(0, RTLD_NOW);
00163     if (program && dlsym(program, "pthread_create"))
00164     {
00165       s_pthreads = true;
00166       pthread_key_create(&s_bufkey, 0);
00167       pthread_key_create(&s_flagkey, 0);
00168       pthread_setspecific(s_flagkey, new IgProfAtomic(1));
00169     }
00170     dlclose(program);
00171 
00172     const char *target = getenv("IGPROF_TARGET");
00173     s_mainthread = pthread_self();
00174     if (target && ! strstr(program_invocation_name, target))
00175     {
00176       IgProf::debug("Current process not selected for profiling:"
00177                     " process '%s' does not match '%s'\n",
00178                     program_invocation_name, target);
00179       return s_activated = false;
00180     }
00181 
00182     itimerval precision;
00183     itimerval interval = { { 0, 10000 }, { 100, 0 } };
00184     itimerval nullified = { { 0, 0 }, { 0, 0 } };
00185     setitimer(ITIMER_PROF, &interval, 0);
00186     getitimer(ITIMER_PROF, &precision);
00187     setitimer(ITIMER_PROF, &nullified, 0);
00188     s_clockres = (precision.it_interval.tv_sec
00189                   + 1e-6 * precision.it_interval.tv_usec);
00190 
00191     IgProf::debug("Activated in %s, timing resolution %f, %s,"
00192                   " main thread id 0x%lx\n",
00193                   program_invocation_name, s_clockres,
00194                   s_pthreads ? "multi-threaded" : "no threads",
00195                   s_mainthread);
00196     IgProf::debug("Options: %s\n", options);
00197 
00198     IgHook::hook(doexit_hook_main.raw);
00199     IgHook::hook(doexit_hook_main2.raw);
00200     IgHook::hook(dokill_hook_main.raw);
00201 #if __linux
00202     if (doexit_hook_main.raw.chain)  IgHook::hook(doexit_hook_libc.raw);
00203     if (doexit_hook_main2.raw.chain) IgHook::hook(doexit_hook_libc2.raw);
00204     if (dokill_hook_main.raw.chain)  IgHook::hook(dokill_hook_libc.raw);
00205 #endif
00206     if (s_pthreads)
00207     {
00208       IgHook::hook(dopthread_create_hook_main.raw);
00209 #if __linux
00210       IgHook::hook(dopthread_create_hook_pthread20.raw);
00211       IgHook::hook(dopthread_create_hook_pthread21.raw);
00212 #endif
00213     }
00214     s_activated = true;
00215     s_enabled = 1;
00216   }
00217 
00218   if (! s_activated)
00219     return false;
00220 
00221   if (! moduleid)
00222     return true;
00223 
00224   IgProf::disable(true);
00225 
00226   if (! s_masterbuf)
00227   {
00228     s_masterbuf = new (s_masterbufdata) IgProfTrace(IgProfTrace::OptResources);
00229     s_symcache = new (s_symcachedata) IgProfSymCache;
00230   }
00231 
00232   int modid;
00233   for (modid = 0; modid < N_MODULES; ++modid)
00234     if (! s_bufs[modid].buf)
00235     {
00236       initBuf(s_bufs[modid], perthread);
00237       *moduleid = modid;
00238       break;
00239     }
00240 
00241   if (modid == N_MODULES)
00242   {
00243     IgProf::debug("Too many profilers enabled (%d), please"
00244                   " rebuild IgProf with larger N_MODULES\n",
00245                   N_MODULES);
00246     abort ();
00247   }
00248 
00249   if (threadinit)
00250     threadinits().push_back(threadinit);
00251 
00252   IgProf::enable(true);
00253   return true;
00254 }

void IgProf::initThread ( void   )  [static]

Setup a thread so it can be used in profiling.

This should be called for every thread that will participate in profiling.

Definition at line 264 of file IgProf.cc.

References IgProfTraceAlloc::buf, enabled(), i, initBuf(), N_MODULES, s_bufkey, s_bufs, and s_flagkey.

Referenced by threadWrapper().

00265 {
00266   IgProfTraceAlloc *bufs = new IgProfTraceAlloc[N_MODULES];
00267   memset(bufs, 0, N_MODULES * sizeof(*bufs));
00268   pthread_setspecific(s_bufkey, bufs);
00269 
00270   IgProfAtomic *enabled = new IgProfAtomic(1);
00271   pthread_setspecific(s_flagkey, enabled);
00272 
00273   for (int i = 0; i < N_MODULES && s_bufs[i].buf; ++i)
00274     if (s_bufs[i].perthread)
00275       initBuf(bufs[i], true);
00276 }

bool IgProf::isMultiThreaded ( void   )  [static]

Return true if the process was linked against threading package.

Definition at line 258 of file IgProf.cc.

References s_pthreads.

Referenced by enableSignalHandler().

00259 { return s_pthreads; }

const char * IgProf::options ( void   )  [static]

Get user-provided profiling options.

Definition at line 386 of file IgProf.cc.

References s_options.

Referenced by initialize(), and initialize().

00387 {
00388   if (! s_options)
00389     s_options = getenv("IGPROF");
00390   return s_options;
00391 }

int IgProf::panic ( const char *  file,
int  line,
const char *  func,
const char *  expr 
) [static]

Internal assertion helper routine.

Definition at line 395 of file IgProf.cc.

References disable(), i, offset, IgHookTrace::stacktrace(), IgHookTrace::symbol(), and GsfMatrixTools::trace().

00396 {
00397   IgProf::disable(true);
00398 
00399   fprintf (stderr, "%s: %s:%d: %s: assertion failure: %s\n",
00400            program_invocation_name, file, line, func, expr);
00401 
00402   void *trace [128];
00403   int levels = IgHookTrace::stacktrace(trace, 128);
00404   for (int i = 2; i < levels; ++i)
00405   {
00406     const char  *sym = 0;
00407     const char  *lib = 0;
00408     int         offset = 0;
00409     int         liboffset = 0;
00410 
00411     IgHookTrace::symbol(trace[i], sym, lib, offset, liboffset);
00412     fprintf(stderr, "  %p %s + %d [%s + %d]\n",
00413             trace[i], sym ? sym : "?", offset, lib ? lib : "?", liboffset);
00414   }
00415 
00416   // abort();
00417   return 1;
00418 }


The documentation for this class was generated from the following files:
Generated on Tue Jun 9 18:25:25 2009 for CMSSW by  doxygen 1.5.4