2009-12-17 Rafael Avila de Espindola <espindola@google.com>
authorRafael Ávila de Espíndola <respindola@mozilla.com>
Thu, 17 Dec 2009 16:02:03 +0000 (16:02 +0000)
committerRafael Ávila de Espíndola <respindola@mozilla.com>
Thu, 17 Dec 2009 16:02:03 +0000 (16:02 +0000)
* Makefile.am (CCFILES): Add timer.cc.
(HFILES): Add timer.h.
* configure.ac: Check for sysconf and times.
* main.cc: include timer.h.
(main): Use Timer instead of get_run_time.
* timer.cc: New.
* timer.h: New.
* workqueue.cc: include timer.h.
(Workqueue::find_and_run_task):
Report user, sys and wall time.
* Makefile.in: Regenerate.
* config.in: Regenerate.
* configure: Regenerate.

gold/ChangeLog
gold/Makefile.am
gold/Makefile.in
gold/config.in
gold/configure
gold/configure.ac
gold/main.cc
gold/timer.cc [new file with mode: 0644]
gold/timer.h [new file with mode: 0644]
gold/workqueue.cc

index b6cd629ab5171321b07bc2ca7e7ad50e8047be6a..14cce02167f4c788ad4138af899da3473fbd648d 100644 (file)
@@ -1,3 +1,19 @@
+2009-12-17  Rafael Avila de Espindola  <espindola@google.com>
+
+       * Makefile.am (CCFILES): Add timer.cc.
+       (HFILES): Add timer.h.
+       * configure.ac: Check for sysconf and times.
+       * main.cc: include timer.h.
+       (main): Use Timer instead of get_run_time.
+       * timer.cc: New.
+       * timer.h: New.
+       * workqueue.cc: include timer.h.
+       (Workqueue::find_and_run_task):
+       Report user, sys and wall time.
+       * Makefile.in: Regenerate.
+       * config.in: Regenerate.
+       * configure: Regenerate.
+
 2009-12-16  Doug Kwan  <dougkwan@google.com>
 
        * arm.cc (Arm_relobj::scan_sections_for_stubs): Exclude ICF-eliminated
index 6afca178b44c22b2b018d712448dd07f3812f771..9c9ed1a7370d95cbe4b71fd77837d474e4dcf06e 100644 (file)
@@ -78,6 +78,7 @@ CCFILES = \
        symtab.cc \
        target.cc \
        target-select.cc \
+       timer.cc \
        version.cc \
        workqueue.cc \
        workqueue-threads.cc
@@ -124,6 +125,7 @@ HFILES = \
        target.h \
        target-reloc.h \
        target-select.h \
+       timer.h \
        tls.h \
        token.h \
        workqueue.h \
index 38bd887fbe33dfce7f2c75dc062aa5e9cfd81813..b6e743a91f0890feacff4f322bb2e806e71b76ea 100644 (file)
@@ -87,8 +87,8 @@ am__objects_1 = archive.$(OBJEXT) attributes.$(OBJEXT) \
        reduced_debug_output.$(OBJEXT) reloc.$(OBJEXT) \
        resolve.$(OBJEXT) script-sections.$(OBJEXT) script.$(OBJEXT) \
        stringpool.$(OBJEXT) symtab.$(OBJEXT) target.$(OBJEXT) \
-       target-select.$(OBJEXT) version.$(OBJEXT) workqueue.$(OBJEXT) \
-       workqueue-threads.$(OBJEXT)
+       target-select.$(OBJEXT) timer.$(OBJEXT) version.$(OBJEXT) \
+       workqueue.$(OBJEXT) workqueue-threads.$(OBJEXT)
 am__objects_2 =
 am__objects_3 = yyscript.$(OBJEXT)
 am_libgold_a_OBJECTS = $(am__objects_1) $(am__objects_2) \
@@ -392,6 +392,7 @@ CCFILES = \
        symtab.cc \
        target.cc \
        target-select.cc \
+       timer.cc \
        version.cc \
        workqueue.cc \
        workqueue-threads.cc
@@ -438,6 +439,7 @@ HFILES = \
        target.h \
        target-reloc.h \
        target-select.h \
+       timer.h \
        tls.h \
        token.h \
        workqueue.h \
@@ -641,6 +643,7 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/symtab.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/target-select.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/target.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/timer.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/version.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/workqueue-threads.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/workqueue.Po@am__quote@
index 745510b081cc63a8475933fbda69a5c47ee261c9..7a824b045a04860856d77e66d9ace2d7b5749c92 100644 (file)
 /* Define to 1 if you have the <string.h> header file. */
 #undef HAVE_STRING_H
 
+/* Define to 1 if you have the `sysconf' function. */
+#undef HAVE_SYSCONF
+
 /* Define to 1 if you have the <sys/stat.h> header file. */
 #undef HAVE_SYS_STAT_H
 
 /* Define if attributes work on C++ templates */
 #undef HAVE_TEMPLATE_ATTRIBUTES
 
+/* Define to 1 if you have the `times' function. */
+#undef HAVE_TIMES
+
 /* Define to 1 if you have the <tr1/unordered_map> header file. */
 #undef HAVE_TR1_UNORDERED_MAP
 
index 30bd132d749f5344464dc62f912344f0405602ad..1bb2d3dee21d59d67047ec20ed4dbd6e786b540f 100755 (executable)
@@ -6701,7 +6701,7 @@ fi
 
 done
 
-for ac_func in mallinfo posix_fallocate readv
+for ac_func in mallinfo posix_fallocate readv sysconf times
 do :
   as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
 ac_fn_cxx_check_func "$LINENO" "$ac_func" "$as_ac_var"
index 2f9cc43a99ebef2578980186d3fb4ea6e2dce533..f279b450a20d58e17533fa1e1dd1161c88057a16 100644 (file)
@@ -338,7 +338,7 @@ AC_LANG_PUSH(C++)
 AC_CHECK_HEADERS(tr1/unordered_set tr1/unordered_map)
 AC_CHECK_HEADERS(ext/hash_map ext/hash_set)
 AC_CHECK_HEADERS(byteswap.h)
-AC_CHECK_FUNCS(mallinfo posix_fallocate readv)
+AC_CHECK_FUNCS(mallinfo posix_fallocate readv sysconf times)
 AC_CHECK_DECLS([basename, ffs, asprintf, vasprintf, snprintf, vsnprintf, strverscmp, strndup, memmem])
 
 # Use of ::std::tr1::unordered_map::rehash causes undefined symbols
index 66e8b244318fee8cf0ff4a1964bc88b4d4a3a454..c9d0d7966c411ad9c2fa8f0733c4cb0c7d90dad9 100644 (file)
@@ -46,6 +46,7 @@
 #include "gc.h"
 #include "icf.h"
 #include "incremental.h"
+#include "timer.h"
 
 using namespace gold;
 
@@ -161,9 +162,9 @@ main(int argc, char** argv)
   Command_line command_line;
   command_line.process(argc - 1, const_cast<const char**>(argv + 1));
 
-  long start_time = 0;
+  Timer timer;
   if (command_line.options().stats())
-    start_time = get_run_time();
+    timer.start();
 
   // Store some options in the globally accessible parameters.
   set_parameters_options(&command_line.options());
@@ -247,9 +248,15 @@ main(int argc, char** argv)
 
   if (command_line.options().stats())
     {
-      long run_time = get_run_time() - start_time;
-      fprintf(stderr, _("%s: total run time: %ld.%06ld seconds\n"),
-             program_name, run_time / 1000000, run_time % 1000000);
+      Timer::TimeStats elapsed = timer.get_elapsed_time();
+      fprintf(stderr,
+             _("%s: total run time: " \
+               "(user: %ld.%06ld sys: %ld.%06ld wall: %ld.%06ld)\n"),
+              program_name,
+              elapsed.user / 1000, (elapsed.user % 1000) * 1000,
+              elapsed.sys / 1000, (elapsed.user % 1000) * 1000,
+              elapsed.wall / 1000, (elapsed.wall % 1000) * 1000);
+
 #ifdef HAVE_MALLINFO
       struct mallinfo m = mallinfo();
       fprintf(stderr, _("%s: total space allocated by malloc: %d bytes\n"),
diff --git a/gold/timer.cc b/gold/timer.cc
new file mode 100644 (file)
index 0000000..ec51bc9
--- /dev/null
@@ -0,0 +1,107 @@
+// timer.cc -- helper class for time accounting
+
+// Copyright 2009 Free Software Foundation, Inc.
+// Written by Rafael Avila de Espindola <espindola@google.com>.
+
+// This file is part of gold.
+
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+// MA 02110-1301, USA.
+
+#include "gold.h"
+
+#include <sys/times.h>
+
+#include "libiberty.h"
+
+#include "timer.h"
+
+namespace gold
+{
+
+// Class Timer
+
+Timer::Timer()
+{
+  this->start_time_.wall = 0;
+  this->start_time_.user = 0;
+  this->start_time_.sys = 0;
+}
+
+// Start couting the time.
+void
+Timer::start ()
+{
+  this->get_time(&this->start_time_);
+}
+
+#if HAVE_SYSCONF && defined _SC_CLK_TCK
+# define TICKS_PER_SECOND sysconf (_SC_CLK_TCK) /* POSIX 1003.1-1996 */
+#else
+# ifdef CLK_TCK
+#  define TICKS_PER_SECOND CLK_TCK /* POSIX 1003.1-1988; obsolescent */
+# else
+#  ifdef HZ
+#   define TICKS_PER_SECOND HZ  /* traditional UNIX */
+#  else
+#   define TICKS_PER_SECOND 100 /* often the correct value */
+#  endif
+# endif
+#endif
+
+// times returns statistics in clock_t units. This variable will hold the
+// conversion factor to seconds. We use a variable that is initialize once
+// because sysconf can be slow.
+static long ticks_per_sec;
+class Timer_init
+{
+ public:
+  Timer_init()
+  {
+    ticks_per_sec = TICKS_PER_SECOND;
+  }
+};
+Timer_init timer_init;
+
+// Write the current time infortamion.
+void
+Timer::get_time (TimeStats *now)
+{
+#ifdef HAVE_TIMES
+  tms t;
+  now->wall = (times(&t) * 1000) / ticks_per_sec;
+  now->user = (t.tms_utime * 1000) / ticks_per_sec;
+  now->sys  = (t.tms_stime * 1000) / ticks_per_sec;
+#else
+  now->wall = get_run_time() / 1000;
+  now->user = 0;
+  now->sys = 0;
+#endif
+}
+
+// Return the stats since start was called.
+Timer::TimeStats
+Timer::get_elapsed_time ()
+{
+  TimeStats now;
+  this->get_time(&now);
+  TimeStats delta;
+  delta.wall = now.wall - this->start_time_.wall;
+  delta.user = now.user - this->start_time_.user;
+  delta.sys = now.sys - this->start_time_.sys;
+  return delta;
+}
+
+}
diff --git a/gold/timer.h b/gold/timer.h
new file mode 100644 (file)
index 0000000..ea360c2
--- /dev/null
@@ -0,0 +1,69 @@
+// timer.h -- helper class for time accounting   -*- C++ -*-
+
+// Copyright 2009 Free Software Foundation, Inc.
+// Written by Rafael Avila de Espindola <espindola@google.com>.
+
+// This file is part of gold.
+
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+// MA 02110-1301, USA.
+
+#ifndef GOLD_TIMER_H
+#define GOLD_TIMER_H
+
+namespace gold
+{
+
+class Timer
+{
+ public:
+  // Used to report time statistics. All fields are in milliseconds.
+  struct TimeStats
+  {
+    /* User time in this process.  */
+    long user;
+
+    /* System time in this process.  */
+    long sys;
+
+    /* Wall clock time.  */
+    long wall;
+  };
+
+  Timer();
+
+  // Return the stats since start was called.
+  TimeStats
+  get_elapsed_time();
+
+  // Start couting the time.
+  void
+  start();
+
+ private:
+  // This class cannot be copied.
+  Timer(const Timer&);
+  Timer& operator=(const Timer&);
+
+  // Write the current time infortamion.
+  static void
+  get_time(TimeStats *now);
+
+  // The time of the last call to start.
+  TimeStats start_time_;
+};
+
+}
+#endif
index 18c39003abdadbbd04bcc9cec1c5ac239e4c7690..c713dca1dc28f4363f9b7a2ff84b868e825c31ec 100644 (file)
@@ -24,6 +24,7 @@
 
 #include "debug.h"
 #include "options.h"
+#include "timer.h"
 #include "workqueue.h"
 #include "workqueue-internal.h"
 
@@ -311,10 +312,24 @@ Workqueue::find_and_run_task(int thread_number)
       gold_debug(DEBUG_TASK, "%3d running   task %s", thread_number,
                 t->name().c_str());
 
+      Timer timer;
+      if (is_debugging_enabled(DEBUG_TASK))
+        timer.start();
+
       t->run(this);
 
-      gold_debug(DEBUG_TASK, "%3d completed task %s", thread_number,
-                t->name().c_str());
+      if (is_debugging_enabled(DEBUG_TASK))
+        {
+          Timer::TimeStats elapsed = timer.get_elapsed_time();
+
+          gold_debug(DEBUG_TASK,
+                     "%3d completed task %s "
+                     "(user: %ld.%06ld sys: %ld.%06ld wall: %ld.%06ld)",
+                     thread_number,  t->name().c_str(),
+                     elapsed.user / 1000, (elapsed.user % 1000) * 1000,
+                     elapsed.sys / 1000, (elapsed.user % 1000) * 1000,
+                     elapsed.wall / 1000, (elapsed.wall % 1000) * 1000);
+        }
 
       Task* next;
       {