+++ /dev/null
-/************************************************************
- * SQUID - a library of functions for biological sequence analysis
- * Copyright (C) 1992-2002 Washington University School of Medicine
- *
- * This source code is freely distributed under the terms of the
- * GNU General Public License. See the files COPYRIGHT and LICENSE
- * for details.
- ************************************************************/
-
-/* stopwatch.c
- * SRE, Fri Nov 26 14:54:21 1999 [St. Louis] [HMMER]
- * SRE, Thu Aug 3 08:11:52 2000 [St. Louis] [moved to SQUID]
- *
- * Reporting of cpu/system/elapsed time used by a process.
- * thanks to Warren Gish for assistance.
- *
- * Basic API:
- *
- * Stopwatch_t *w;
- * w = StopwatchCreate();
- *
- * StopwatchStart(w);
- * do_lots_of_stuff;
- * StopwatchStop(w);
- * StopwatchDisplay(stdout, "CPU time: ", w);
- *
- * StopwatchFree(w);
- *
- * Some behavior can be controlled at compile time by #define's:
- *
- * SRE_STRICT_ANSI: By default, stopwatch module assumes that a
- * machine is POSIX-compliant (e.g. has struct tms, sys/times.h,
- * and times()). If compiled with -DSRE_STRICT_ANSI, reverts to
- * pure ANSI C conformant implementation. This simpler system
- * won't report system times, only user and elapsed times.
- *
- * SRE_ENABLE_PVM: If compiled with -DSRE_ENABLE_PVM, the
- * functions StopwatchPVMPack() and StopwatchPVMUnpack()
- * are compiled, providing PVM communications ability.
- *
- * One additional compile-time configuration note:
- * PTHREAD_TIMES_HACK: Linux pthreads, as of RH6.0/glibc-devel-2.1.1-6,
- * appears to interact poorly with times() -- usage times in all
- * but the master thread are lost. A workaround for this bug is
- * to run stopwatches in each worker thread, and accumulate those
- * times back into the master stopwatch using StopwatchInclude().
- * (Just like a PVM implementation has to do.) In HMMER, this
- * behavior is compiled in with -DPTHREAD_TIMES_HACK. No
- * changes are made in stopwatch functions themselves, though;
- * all the extra code is HMMER code. See hmmcalibrate.c for
- * an example.
- *
- * See hmmcalibrate.c for examples of more complex usage
- * in dealing with pthreads and PVM.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#ifdef SRE_ENABLE_PVM
-#include <pvm3.h>
-#endif
-
-#include "stopwatch.h"
-
-/* Function: format_time_string()
- * Date: SRE, Fri Nov 26 15:06:28 1999 [St. Louis]
- *
- * Purpose: Given a number of seconds, format into
- * hh:mm:ss.xx in a provided buffer.
- *
- * Args: buf - allocated space (128 is plenty!)
- * sec - number of seconds
- * do_frac - TRUE (1) to include hundredths of a sec
- */
-static void
-format_time_string(char *buf, double sec, int do_frac)
-{
- int h, m, s, hs;
-
- h = (int) (sec / 3600.);
- m = (int) (sec / 60.) - h * 60;
- s = (int) (sec) - h * 3600 - m * 60;
- if (do_frac) {
- hs = (int) (sec * 100.) - h * 360000 - m * 6000 - s * 100;
- sprintf(buf, "%02d:%02d:%02d.%02d", h,m,s,hs);
- } else {
- sprintf(buf, "%02d:%02d:%02d", h,m,s);
- }
-}
-
-/* Function: StopwatchStart()
- * Date: SRE, Fri Nov 26 15:07:48 1999 [St. Louis]
- *
- * Purpose: Start a stopwatch.
- *
- * Args: w - the watch
- */
-void
-StopwatchStart(Stopwatch_t *w)
-{
- w->t0 = time(NULL);
-#ifdef SRE_STRICT_ANSI
- w->cpu0 = clock();
-#else
- (void) times(&(w->cpu0));
-#endif
-
- w->elapsed = 0.;
- w->user = 0.;
- w->sys = 0.;
-}
-
-/* Function: StopwatchStop()
- * Date: SRE, Fri Nov 26 15:08:16 1999 [St. Louis]
- *
- * Purpose: Stop a stopwatch.
- *
- * The implementation allows "split times":
- * you can stop a watch multiple times, reporting
- * times at multiple points during program
- * execution.
- *
- * Args: w - the watch
- */
-void
-StopwatchStop(Stopwatch_t *w)
-{
- time_t t1;
-#ifdef SRE_STRICT_ANSI
- clock_t cpu1;
-#else
- struct tms cpu1;
- long clk_tck;
-#endif
-
- t1 = time(NULL);
- w->elapsed = difftime(t1, w->t0);
-
-#ifdef SRE_STRICT_ANSI
- cpu1 = clock();
- w->user = (double) (cpu1- w->cpu0) / (double) CLOCKS_PER_SEC;
- w->sys = 0.; /* no way to portably get system time in ANSI C */
-
-#else /* assume we're on a POSIX system by default */
- (void) times(&cpu1);
-
- clk_tck = sysconf(_SC_CLK_TCK);
- w->user = (double) (cpu1.tms_utime + cpu1.tms_cutime -
- w->cpu0.tms_utime - w->cpu0.tms_cutime) /
- (double) clk_tck;
-
- w->sys = (double) (cpu1.tms_stime + cpu1.tms_cstime -
- w->cpu0.tms_stime - w->cpu0.tms_cstime) /
- (double) clk_tck;
-#endif
-}
-
-/* Function: StopwatchInclude()
- * Date: SRE, Fri Nov 26 15:09:34 1999 [St. Louis]
- *
- * Purpose: Merge the cpu and system times from a slave into
- * a master stopwatch. Both watches must be
- * stopped, and should not be stopped again unless
- * You Know What You're Doing.
- *
- * Elapsed time is *not* merged; master is assumed
- * to be keeping track of the wall clock time,
- * and the slave/worker watch is ignored.
- *
- * Used in two cases:
- * 1) PVM; merge in the stopwatch(es) from separate
- * process(es) in a cluster.
- * 2) Threads, for broken pthreads/times() implementations
- * that lose track of cpu times used by spawned
- * threads.
- *
- * Args: w1 - the master stopwatch
- * w2 - the slave/worker watch
- *
- */
-void
-StopwatchInclude(Stopwatch_t *w1, Stopwatch_t *w2)
-{
- w1->user += w2->user;
- w1->sys += w2->sys;
-}
-
-/* Function: StopwatchAlloc(), StopwatchZero(), StopwatchCopy(),
- * StopwatchFree()
- * Date: SRE, Fri Nov 26 15:13:14 1999 [St. Louis]
- *
- * Purpose: The usual creation/manipulation/destruction routines
- * for a stopwatch object.
- */
-Stopwatch_t *
-StopwatchCreate(void)
-{
- Stopwatch_t *w;
- w = malloc(sizeof(Stopwatch_t));
- return w;
-}
-void
-StopwatchZero(Stopwatch_t *w)
-{
- w->elapsed = 0.;
- w->user = 0.;
- w->sys = 0.;
-}
-void
-StopwatchCopy(Stopwatch_t *w1, Stopwatch_t *w2)
-{
- w1->t0 = w2->t0;
-#ifdef SRE_STRICT_ANSI
- w1->cpu0 = w2->cpu0;
-#else
- w1->cpu0.tms_utime = w2->cpu0.tms_utime;
- w1->cpu0.tms_stime = w2->cpu0.tms_stime;
- w1->cpu0.tms_cutime = w2->cpu0.tms_cutime;
- w1->cpu0.tms_cstime = w2->cpu0.tms_cstime;
-#endif
- w1->elapsed = w2->elapsed;
- w1->user = w2->user;
- w1->sys = w2->sys;
-}
-void
-StopwatchFree(Stopwatch_t *w)
-{
- free(w);
-}
-
-
-/* Function: StopwatchDisplay()
- * Date: SRE, Fri Nov 26 15:14:12 1999 [St. Louis]
- *
- * Purpose: Output a usage summary line from a *stopped*
- * stopwatch (the times will reflect the last
- * time StopwatchStop() was called.)
- *
- * For s = "CPU Time: " an example output line is:
- * CPU Time: 142.55u 7.17s 149.72 Elapsed: 00:02:35.00
- *
- * Args: fp - open file for writing (stdout, possibly)
- * s - prefix for the report line
- * w - a (recently stopped) stopwatch
- *
- */
-void
-StopwatchDisplay(FILE *fp, char *s, Stopwatch_t *w)
-{
- char buf[128]; /* (safely holds up to 10^14 years) */
-
- if (s == NULL)
- fputs("CPU Time: ", fp);
- else
- fputs(s, fp);
-
- format_time_string(buf, w->user+w->sys, 1);
-#ifdef SRE_STRICT_ANSI
- fprintf(fp, "%.2fu %s ", w->user, buf);
-#else
- fprintf(fp, "%.2fu %.2fs %s ", w->user, w->sys, buf);
-#endif
-
- format_time_string(buf, w->elapsed, 0);
- fprintf(fp, "Elapsed: %s\n", buf);
-}
-
-#ifdef SRE_ENABLE_PVM
-/* Function: StopwatchPVMPack(), StopwatchPVMUnpack()
- * Date: SRE, Fri Nov 26 15:22:04 1999 [St. Louis]
- *
- * Purpose: Transmission of stopwatch data in a PVM
- * cluster.
- */
-void
-StopwatchPVMPack(Stopwatch_t *w)
-{
- pvm_pkdouble(&(w->elapsed), 1, 1);
- pvm_pkdouble(&(w->user), 1, 1);
- pvm_pkdouble(&(w->sys), 1, 1);
-}
-void
-StopwatchPVMUnpack(Stopwatch_t *w)
-{
- pvm_upkdouble(&(w->elapsed), 1, 1);
- pvm_upkdouble(&(w->user), 1, 1);
- pvm_upkdouble(&(w->sys), 1, 1);
-}
-#endif /*SRE_ENABLE_PVM*/
-
-
-#ifdef TESTDRIVER
-int
-main(int argc, char **argv)
-{
- Stopwatch_t stopwatch;
-
- StopwatchStart(&stopwatch);
-
- sleep(5);
-
- StopwatchStop(&stopwatch);
- StopwatchDisplay(stdout, "CPU Time: ", &stopwatch);
-}
-#endif