This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: time usage for subprocesses [NEW PATCH]
- To: law at cygnus dot com
- Subject: Re: time usage for subprocesses [NEW PATCH]
- From: Zack Weinberg <zack at bitmover dot com>
- Date: Thu, 12 Aug 1999 19:57:28 -0700
- cc: egcs-patches at egcs dot cygnus dot com
Jeffrey A Law wrote:
>
> In message <199908070639.XAA08070@zack.bitmover.com>you write:
> > Jeffrey A Law wrote:
> > > But it's trivial to get deltas given the rusage stats as you wait on
> > > each process in succession.
> >
> > My impression was that times() and getrusage(RUSAGE_CHILDREN, ...)
> > would give me cumulative execution times for all the children up to
> > the moment I made the call. Is that not the case?
> Right, but all that means is you have to subtract the last sample from the
> new sample to get the run time for whatever pass you just ran.
I get it now... and doing it this way, I don't have to modify
libiberty. On the other hand, I have to turn off -pipe, but that's
OK. New patch follows.
zw
1999-08-12 19:50 -0700 Zack Weinberg <zack@bitmover.com>
* gcc.c (report_times): New flag.
(execute): If HAVE_GETRUSAGE, and report_times is set, then
call getrusage for each child process in turn, and print the
user and system time consumed.
(process_command): If -time is given, then set report_times
flag and turn off -pipe.
(option_map): Map --time to -time.
(display_help): Document -time option.
* configure.in: Check for getrusage.
* acconfig.h: Add NEED_DECLARATION_GETRUSAGE.
Index: gcc.c
===================================================================
RCS file: /cvs/egcs/egcs/gcc/gcc.c,v
retrieving revision 1.107
diff -u -r1.107 gcc.c
--- gcc.c 1999/08/05 09:16:26 1.107
+++ gcc.c 1999/08/13 02:57:46
@@ -43,6 +43,13 @@
#define exit __posix_exit
#endif
+#ifdef HAVE_SYS_RESOURCE_H
+#include <sys/resource.h>
+#endif
+#ifdef NEED_DECLARATION_GETRUSAGE
+extern int getrusage(int, struct rusage *);
+#endif
+
/* By default there is no special suffix for executables. */
#ifdef EXECUTABLE_SUFFIX
#define HAVE_EXECUTABLE_SUFFIX
@@ -125,6 +132,11 @@
static int verbose_flag;
+/* Flag indicating whether we should report subprocess execution times
+ (if this is supported by the system - see pexecute.c). */
+
+static int report_times;
+
/* Nonzero means write "temp" files in source directory
and use the source file's name in them, and don't delete them. */
@@ -166,6 +178,12 @@
static struct obstack collect_obstack;
+/* These structs are used to collect resource usage information for
+ subprocesses. */
+#ifdef HAVE_GETRUSAGE
+static struct rusage rus, prus;
+#endif
+
extern char *version_string;
/* Forward declaration for prototypes. */
@@ -875,6 +893,7 @@
{"--std", "-std=", "aj"},
{"--symbolic", "-symbolic", 0},
{"--target", "-b", "a"},
+ {"--time", "-time", 0},
{"--trace-includes", "-H", 0},
{"--traditional", "-traditional", 0},
{"--traditional-cpp", "-traditional-cpp", 0},
@@ -2336,6 +2355,10 @@
{
int ret_code = 0;
+#ifdef HAVE_GETRUSAGE
+ struct timeval d;
+ double ut, st;
+#endif
for (i = 0; i < n_commands; )
{
@@ -2347,6 +2370,25 @@
if (pid < 0)
abort ();
+#ifdef HAVE_GETRUSAGE
+ if (report_times)
+ {
+ /* getrusage returns the total resource usage of all children
+ up to now. Copy the previous values into prus, get the
+ current statistics, then take the difference. */
+
+ prus = rus;
+ getrusage (RUSAGE_CHILDREN, &rus);
+ d.tv_sec = rus.ru_utime.tv_sec - prus.ru_utime.tv_sec;
+ d.tv_usec = rus.ru_utime.tv_usec - prus.ru_utime.tv_usec;
+ ut = (double)d.tv_sec + (double)d.tv_usec / 1.0e6;
+
+ d.tv_sec = rus.ru_stime.tv_sec - prus.ru_stime.tv_sec;
+ d.tv_usec = rus.ru_stime.tv_usec - prus.ru_utime.tv_usec;
+ st = (double)d.tv_sec + (double)d.tv_usec / 1.0e6;
+ }
+#endif
+
for (j = 0; j < n_commands; j++)
if (commands[j].pid == pid)
{
@@ -2364,6 +2406,10 @@
&& WEXITSTATUS (status) >= MIN_FATAL_STATUS)
ret_code = -1;
}
+#ifdef HAVE_GETRUSAGE
+ if (report_times && ut + st != 0)
+ notice ("# %s %.2f %.2f\n", commands[j].prog, ut, st);
+#endif
break;
}
}
@@ -2504,6 +2550,7 @@
printf (" -Xlinker <arg> Pass <arg> on to the linker\n");
printf (" -save-temps Do not delete intermediate files\n");
printf (" -pipe Use pipes rather than intermediate files\n");
+ printf (" -time Time the execution of each subprocess\n");
printf (" -specs=<file> Override builtin specs with the contents of <file>\n");
printf (" -std=<standard> Assume that the input sources are for <standard>\n");
printf (" -B <directory> Add <directory> to the compiler's search paths\n");
@@ -2888,6 +2935,8 @@
user_specs_head = user;
user_specs_tail = user;
}
+ else if (strcmp (argv[i], "-time") == 0)
+ report_times = 1;
else if (argv[i][0] == '-' && argv[i][1] != 0)
{
register char *p = &argv[i][1];
@@ -3227,10 +3276,20 @@
else if (strcmp (argv[i], "-specs") == 0)
i++;
else if (strncmp (argv[i], "-specs=", 7) == 0)
+ ;
+ else if (strcmp (argv[i], "-time") == 0)
;
- /* -save-temps overrides -pipe, so that temp files are produced */
- else if (save_temps_flag && strcmp (argv[i], "-pipe") == 0)
- error ("Warning: -pipe ignored since -save-temps specified");
+ else if ((save_temps_flag || report_times)
+ && strcmp (argv[i], "-pipe") == 0)
+ {
+ /* -save-temps overrides -pipe, so that temp files are produced */
+ if (save_temps_flag)
+ error ("Warning: -pipe ignored since -save-temps specified");
+ /* -time overrides -pipe because we can't get correct stats when
+ multiple children are running at once. */
+ else if (report_times)
+ error ("Warning: -pipe ignored since -time specified");
+ }
else if (argv[i][0] == '-' && argv[i][1] != 0)
{
register char *p = &argv[i][1];
Index: configure.in
===================================================================
RCS file: /cvs/egcs/egcs/gcc/configure.in,v
retrieving revision 1.274
diff -u -r1.274 configure.in
--- configure.in 1999/08/12 22:31:16 1.274
+++ configure.in 1999/08/13 02:57:46
@@ -339,7 +339,9 @@
AC_HEADER_TIME
GCC_HEADER_STRING
AC_HEADER_SYS_WAIT
-AC_CHECK_HEADERS(limits.h stddef.h string.h strings.h stdlib.h time.h fcntl.h unistd.h stab.h sys/file.h sys/time.h sys/resource.h sys/param.h sys/times.h sys/stat.h direct.h)
+AC_CHECK_HEADERS(limits.h stddef.h string.h strings.h stdlib.h time.h \
+ fcntl.h unistd.h stab.h sys/file.h sys/time.h \
+ sys/resource.h sys/param.h sys/times.h sys/stat.h direct.h)
# Check for thread headers.
AC_CHECK_HEADER(thread.h, [have_thread_h=yes], [have_thread_h=])
@@ -379,7 +381,7 @@
AC_CHECK_FUNCS(strtoul bsearch strerror putenv popen bcopy bzero bcmp \
index rindex strchr strrchr kill getrlimit setrlimit atoll atoq \
sysconf isascii gettimeofday strsignal putc_unlocked fputc_unlocked \
- fputs_unlocked)
+ fputs_unlocked getrusage)
# Make sure wchar_t is available
#AC_CHECK_TYPE(wchar_t, unsigned int)
@@ -401,7 +403,7 @@
index rindex getenv atol sbrk abort atof strerror getcwd getwd \
strsignal putc_unlocked fputs_unlocked strstr)
-GCC_NEED_DECLARATIONS(getrlimit setrlimit, [
+GCC_NEED_DECLARATIONS(getrlimit setrlimit getrusage, [
#include <sys/types.h>
#ifdef HAVE_SYS_RESOURCE_H
#include <sys/resource.h>
Index: acconfig.h
===================================================================
RCS file: /cvs/egcs/egcs/gcc/acconfig.h,v
retrieving revision 1.34
diff -u -r1.34 acconfig.h
--- acconfig.h 1999/08/02 22:57:49 1.34
+++ acconfig.h 1999/08/13 02:57:46
@@ -114,6 +114,9 @@
/* Whether setrlimit must be declared even if <sys/resource.h> is included. */
#undef NEED_DECLARATION_SETRLIMIT
+/* Whether getrusage must be declared even if <sys/resource.h> is included. */
+#undef NEED_DECLARATION_GETRUSAGE
+
/* Whether putc_unlocked must be declared even if <stdio.h> is included. */
#undef NEED_DECLARATION_PUTC_UNLOCKED