]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
timers: store internal time stamps as time_t instead of doubles
authorDaniel Stenberg <daniel@haxx.se>
Wed, 7 Jun 2017 11:16:56 +0000 (13:16 +0200)
committerDaniel Stenberg <daniel@haxx.se>
Wed, 14 Jun 2017 14:46:39 +0000 (15:46 +0100)
This gives us accurate precision and it allows us to avoid storing "no
time" for systems with too low timer resolution as we then bump the time
up to 1 microsecond. Should fix test 573 on windows.

Remove the now unused curlx_tvdiff_secs() function.

Maintains the external getinfo() API with using doubles.

Fixes #1531

lib/getinfo.c
lib/progress.c
lib/timeval.c
lib/timeval.h
lib/urldata.h

index a1ce5058e8e0372c0a1d6920905b986e64a90d93..b94a5359acb8df130b503796c45828ba8ce902d9 100644 (file)
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -246,27 +246,29 @@ static CURLcode getinfo_long(struct Curl_easy *data, CURLINFO info,
   return CURLE_OK;
 }
 
+#define DOUBLE_SECS(x) (double)(x)/1000000
+
 static CURLcode getinfo_double(struct Curl_easy *data, CURLINFO info,
                                double *param_doublep)
 {
   switch(info) {
   case CURLINFO_TOTAL_TIME:
-    *param_doublep = data->progress.timespent;
+    *param_doublep = DOUBLE_SECS(data->progress.timespent);
     break;
   case CURLINFO_NAMELOOKUP_TIME:
-    *param_doublep = data->progress.t_nslookup;
+    *param_doublep = DOUBLE_SECS(data->progress.t_nslookup);
     break;
   case CURLINFO_CONNECT_TIME:
-    *param_doublep = data->progress.t_connect;
+    *param_doublep = DOUBLE_SECS(data->progress.t_connect);
     break;
   case CURLINFO_APPCONNECT_TIME:
-    *param_doublep = data->progress.t_appconnect;
+    *param_doublep = DOUBLE_SECS(data->progress.t_appconnect);
     break;
   case CURLINFO_PRETRANSFER_TIME:
-    *param_doublep =  data->progress.t_pretransfer;
+    *param_doublep = DOUBLE_SECS(data->progress.t_pretransfer);
     break;
   case CURLINFO_STARTTRANSFER_TIME:
-    *param_doublep = data->progress.t_starttransfer;
+    *param_doublep = DOUBLE_SECS(data->progress.t_starttransfer);
     break;
   case CURLINFO_SIZE_UPLOAD:
     *param_doublep =  (double)data->progress.uploaded;
@@ -289,7 +291,7 @@ static CURLcode getinfo_double(struct Curl_easy *data, CURLINFO info,
       (double)data->progress.size_ul:-1;
     break;
   case CURLINFO_REDIRECT_TIME:
-    *param_doublep =  data->progress.t_redirect;
+    *param_doublep = DOUBLE_SECS(data->progress.t_redirect);
     break;
 
   default:
index cfaf4049e526b67fa6fceb689bb396ffc494b0ce..1996d78dccd20c2e304d488146d6430da3c6702d 100644 (file)
@@ -152,10 +152,10 @@ int Curl_pgrsDone(struct connectdata *conn)
 /* reset all times except redirect, and reset the known transfer sizes */
 void Curl_pgrsResetTimesSizes(struct Curl_easy *data)
 {
-  data->progress.t_nslookup = 0.0;
-  data->progress.t_connect = 0.0;
-  data->progress.t_pretransfer = 0.0;
-  data->progress.t_starttransfer = 0.0;
+  data->progress.t_nslookup = 0;
+  data->progress.t_connect = 0;
+  data->progress.t_pretransfer = 0;
+  data->progress.t_starttransfer = 0;
 
   Curl_pgrsSetDownloadSize(data, -1);
   Curl_pgrsSetUploadSize(data, -1);
@@ -164,6 +164,7 @@ void Curl_pgrsResetTimesSizes(struct Curl_easy *data)
 void Curl_pgrsTime(struct Curl_easy *data, timerid timer)
 {
   struct timeval now = Curl_tvnow();
+  time_t *delta = NULL;
 
   switch(timer) {
   default:
@@ -178,38 +179,37 @@ void Curl_pgrsTime(struct Curl_easy *data, timerid timer)
     /* This is set at the start of each single fetch */
     data->progress.t_startsingle = now;
     break;
-
   case TIMER_STARTACCEPT:
-    data->progress.t_acceptdata = Curl_tvnow();
+    data->progress.t_acceptdata = now;
     break;
-
   case TIMER_NAMELOOKUP:
-    data->progress.t_nslookup =
-      Curl_tvdiff_secs(now, data->progress.t_startsingle);
+    delta = &data->progress.t_nslookup;
     break;
   case TIMER_CONNECT:
-    data->progress.t_connect =
-      Curl_tvdiff_secs(now, data->progress.t_startsingle);
+    delta = &data->progress.t_connect;
     break;
   case TIMER_APPCONNECT:
-    data->progress.t_appconnect =
-      Curl_tvdiff_secs(now, data->progress.t_startsingle);
+    delta = &data->progress.t_appconnect;
     break;
   case TIMER_PRETRANSFER:
-    data->progress.t_pretransfer =
-      Curl_tvdiff_secs(now, data->progress.t_startsingle);
+    delta = &data->progress.t_pretransfer;
     break;
   case TIMER_STARTTRANSFER:
-    data->progress.t_starttransfer =
-      Curl_tvdiff_secs(now, data->progress.t_startsingle);
+    delta = &data->progress.t_starttransfer;
     break;
   case TIMER_POSTRANSFER:
     /* this is the normal end-of-transfer thing */
     break;
   case TIMER_REDIRECT:
-    data->progress.t_redirect = Curl_tvdiff_secs(now, data->progress.start);
+    data->progress.t_redirect = Curl_tvdiff_us(now, data->progress.start);
     break;
   }
+  if(delta) {
+    time_t us = Curl_tvdiff_us(now, data->progress.t_startsingle);
+    if(!us)
+      us++; /* make sure at least one microsecond passed */
+    *delta = us;
+  }
 }
 
 void Curl_pgrsStartNow(struct Curl_easy *data)
@@ -361,17 +361,17 @@ int Curl_pgrsUpdate(struct connectdata *conn)
   now = Curl_tvnow(); /* what time is it */
 
   /* The time spent so far (from the start) */
-  data->progress.timespent = curlx_tvdiff_secs(now, data->progress.start);
+  data->progress.timespent = Curl_tvdiff_us(now, data->progress.start);
   timespent = (curl_off_t)data->progress.timespent;
 
   /* The average download speed this far */
   data->progress.dlspeed = (curl_off_t)
-    ((double)data->progress.downloaded/
+    (data->progress.downloaded/
      (data->progress.timespent>0?data->progress.timespent:1));
 
   /* The average upload speed this far */
   data->progress.ulspeed = (curl_off_t)
-    ((double)data->progress.uploaded/
+    (data->progress.uploaded/
      (data->progress.timespent>0?data->progress.timespent:1));
 
   /* Calculations done at most once a second, unless end is reached */
index bed44c573f61a7df57f6073fcf60abea9bc7c51e..1012b4e39d72335db4aab9b14a260d654099e152 100644 (file)
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -130,14 +130,24 @@ time_t curlx_tvdiff(struct timeval newer, struct timeval older)
 }
 
 /*
- * Same as curlx_tvdiff but with full usec resolution.
+ * Make sure that the first argument is the more recent time, as otherwise
+ * we'll get a weird negative time-diff back...
  *
- * Returns: the time difference in seconds with subsecond resolution.
+ * Returns: the time difference in number of microseconds. For too large diffs
+ * it returns max value.
  */
-double curlx_tvdiff_secs(struct timeval newer, struct timeval older)
+time_t Curl_tvdiff_us(struct timeval newer, struct timeval older)
 {
-  if(newer.tv_sec != older.tv_sec)
-    return (double)(newer.tv_sec-older.tv_sec)+
-      (double)(newer.tv_usec-older.tv_usec)/1000000.0;
-  return (double)(newer.tv_usec-older.tv_usec)/1000000.0;
+  time_t diff = newer.tv_sec-older.tv_sec;
+#if SIZEOF_TIME_T < 8
+  /* for 32bit time_t systems */
+  if(diff >= (0x7fffffff/1000000))
+    return 0x7fffffff;
+#else
+  /* for 64bit time_t systems */
+  if(diff >= (0x7fffffffffffffff/1000000))
+    return 0x7fffffffffffffff;
+#endif
+  return (newer.tv_sec-older.tv_sec)*1000000+
+    (time_t)(newer.tv_usec-older.tv_usec);
 }
index 33969354d5db1e517ccc98a62f1779752037a82a..9217018a84c31820140c72c2fb6a72176d5b108c 100644 (file)
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -40,17 +40,17 @@ struct timeval curlx_tvnow(void);
 time_t curlx_tvdiff(struct timeval t1, struct timeval t2);
 
 /*
- * Same as curlx_tvdiff but with full usec resolution.
+ * Make sure that the first argument (t1) is the more recent time and t2 is
+ * the older time, as otherwise you get a weird negative time-diff back...
  *
- * Returns: the time difference in seconds with subsecond resolution.
+ * Returns: the time difference in number of microseconds.
  */
-double curlx_tvdiff_secs(struct timeval t1, struct timeval t2);
+time_t Curl_tvdiff_us(struct timeval newer, struct timeval older);
 
 /* These two defines below exist to provide the older API for library
    internals only. */
 #define Curl_tvnow() curlx_tvnow()
 #define Curl_tvdiff(x,y) curlx_tvdiff(x,y)
-#define Curl_tvdiff_secs(x,y) curlx_tvdiff_secs(x,y)
 
 #endif /* HEADER_CURL_TIMEVAL_H */
 
index d4a4a98dcdc8545a51b99b31b3599055fe0f990d..2d0f46a17a794d0d7d290f7fcbeb5a25ae7ddb04 100644 (file)
@@ -1213,17 +1213,17 @@ struct Progress {
   int width; /* screen width at download start */
   int flags; /* see progress.h */
 
-  double timespent;
+  time_t timespent;
 
   curl_off_t dlspeed;
   curl_off_t ulspeed;
 
-  double t_nslookup;
-  double t_connect;
-  double t_appconnect;
-  double t_pretransfer;
-  double t_starttransfer;
-  double t_redirect;
+  time_t t_nslookup;
+  time_t t_connect;
+  time_t t_appconnect;
+  time_t t_pretransfer;
+  time_t t_starttransfer;
+  time_t t_redirect;
 
   struct timeval start;
   struct timeval t_startsingle;