<<< Date Index >>>     <<< Thread Index >>>

Taking the time into account in progress info



I've written a small clock-times.c program (attached) to test the
performance of the clock() and times() functions.

The times() function is better as it gives the real time (whereas the
clock() function only gives the processor time). Moreover it is fast
enough (see below) IMHO, and not much slower than the clock() function
(e.g. 2 times as slow under Mac OS X, no difference under Linux), so
that I'll focus on this function.

Running "clock-times times" says that more than 200,000 calls per
second can be done on my Mac OS X machine, and more than 2,000,000
per second on my Linux machine. So, even a call per message in the
progress update seems to be reasonable.

Running "clock-times times 0" allows to compare a times() call alone
to a times() call and an output to the terminal. And one can see that
the number of iterations per second is much lower in the second case.
This means that even if calling times() on every processed message is
unacceptable for some users, it may be useful to call it before trying
to output progress information. The attached patch keeps the $*_inc
variables, but the update of progress information is not performed if
the last one occurred less than a 1/4 second before. It allows to set
$read_inc to a low value, whatever command is performed.

Without this patch, I had to set read_inc to 1000 so that fast limit
commands (e.g. a limit on "all") were not slowed down by the output
(in particular through SSH). But this value was too high for some other
much slower commands.

-- 
Vincent Lefèvre <vincent@xxxxxxxxxx> - Web: <http://www.vinc17.org/>
100% accessible validated (X)HTML - Blog: <http://www.vinc17.org/blog/>
Work: CR INRIA - computer arithmetic / Arenaire project (LIP, ENS-Lyon)
/*
 * Performance of clock() and times() function calls.
 */

#define SVNID "$Id: clock-times.c 14961 2006-11-22 01:51:48Z lefevre $"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>     /* for sysconf() */
#include <time.h>       /* for clock() - processor time */
#include <sys/times.h>  /* for times() - real time */

#ifndef NSEC
#define NSEC 3
#endif

#define LOOP(F,U)                       \
  c0 = c1 = (F);                        \
  do                                    \
    {                                   \
      i++;                              \
      c = (F);                          \
      if (d >= 0 && c - c1 >= U * d)    \
        {                               \
          fprintf (stderr, "%u\r", i);  \
          c1 = c;                       \
        }                               \
    }                                   \
  while (c - c0 < U * NSEC);

int main (int argc, char **argv)
{
  unsigned int i = 1;
  double d = -1;

  /* Let's use unsigned long instead of clock_t as this type is sufficient
     for our needs, and to make sure that there is no integer overflow in
     case of clock wrapping (as clock_t is a signed type on some machines,
     e.g. under Linux). */
  unsigned long c0, c1, c;

  if (argc != 2 && argc != 3)
    {
    usage:
      fprintf (stderr, "Usage: clock-times \"clock\" | \"times\" [ num ]\n");
      return 1;
    }

  if (argc == 3)
    {
      char *end;
      d = strtod (argv[2], &end);
    }

  if (strcmp (argv[1], "clock") == 0)
    {
      LOOP (clock (), CLOCKS_PER_SEC)
    }
  else if (strcmp (argv[1], "times") == 0)
    {
      struct tms buffer;
      clock_t clock_ticks;

      clock_ticks = sysconf (_SC_CLK_TCK);
      LOOP (times (&buffer), clock_ticks)
    }
  else
    goto usage;

  printf ("Number of calls: %d\n", i);
  return 0;
}
diff -urd mutt-cvs/PATCHES mutt-new/PATCHES
--- mutt-cvs/PATCHES    2002-12-09 18:44:54.000000000 +0100
+++ mutt-new/PATCHES    2006-11-22 04:15:54.000000000 +0100
@@ -0,0 +1 @@
+patch-1.5.13cvs.vl.time_inc.1
diff -urd mutt-cvs/curs_lib.c mutt-new/curs_lib.c
--- mutt-cvs/curs_lib.c 2006-11-18 23:04:21.000000000 +0100
+++ mutt-new/curs_lib.c 2006-11-22 04:19:58.000000000 +0100
@@ -29,6 +29,8 @@
 
 #include <termios.h>
 #include <sys/types.h>
+#include <sys/times.h>
+#include <time.h>
 #include <fcntl.h>
 #include <stdlib.h>
 #include <unistd.h>
@@ -48,6 +50,10 @@
 static size_t UngetBufLen = 0;
 static event_t *KeyEvent;
 
+static struct tms tms_buf;
+static unsigned long time_inc;
+static unsigned long clk;
+
 void mutt_refresh (void)
 {
   /* don't refresh when we are waiting for a child. */
@@ -332,6 +338,8 @@
 {
   if (!progress)
     return;
+  time_inc = sysconf (_SC_CLK_TCK) / 4;
+  clk = times (&tms_buf);
   memset (progress, 0, sizeof (progress_t));
   progress->inc = inc;
   progress->flags = flags;
@@ -344,6 +352,7 @@
 {
   char posstr[SHORT_STRING];
   short update = 0;
+  unsigned long new_clk;
 
   if (!pos)
   {
@@ -383,10 +392,15 @@
   if (update)
   {
     progress->pos = pos;
-    if (progress->size)
-      mutt_message ("%s %s/%s", progress->msg, posstr, progress->sizestr);
-    else
-      mutt_message ("%s %s", progress->msg, posstr);
+    new_clk = times (&tms_buf);
+    if (new_clk >= clk)
+    {
+      clk = new_clk + time_inc;
+      if (progress->size)
+        mutt_message ("%s %s/%s", progress->msg, posstr, progress->sizestr);
+      else
+        mutt_message ("%s %s", progress->msg, posstr);
+    }
   }
 
   if (pos >= progress->size)