Skip to content

Commit 6c0d5b1

Browse files
committed
util: make monotonic time fn return ms
`git__timer` is now `git_time_monotonic`, and returns milliseconds since an arbitrary epoch. Using a floating point to store the number of seconds elapsed was clever, as it better supports the wide range of precision from the different monotonic clocks of different systems. But we're a version control system, not a real-time clock. Milliseconds is a good enough precision for our work _and_ it's the units that system calls like `poll` take and that our users interact with. Make `git_time_monotonic` return the monotonically increasing number of milliseconds "ticked" since some arbitrary epoch.
1 parent 905e4d1 commit 6c0d5b1

File tree

10 files changed

+66
-53
lines changed

10 files changed

+66
-53
lines changed

src/cli/progress.c

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,10 @@
1515
/*
1616
* Show updates to the percentage and number of objects received
1717
* separately from the throughput to give an accurate progress while
18-
* avoiding too much noise on the screen.
18+
* avoiding too much noise on the screen. (In milliseconds.)
1919
*/
20-
#define PROGRESS_UPDATE_TIME 0.10
21-
#define THROUGHPUT_UPDATE_TIME 1.00
20+
#define PROGRESS_UPDATE_TIME 60
21+
#define THROUGHPUT_UPDATE_TIME 500
2222

2323
#define is_nl(c) ((c) == '\r' || (c) == '\n')
2424

@@ -54,7 +54,7 @@ static int progress_write(cli_progress *progress, bool force, git_str *line)
5454
bool has_nl;
5555
size_t no_nl = no_nl_len(line->ptr, line->size);
5656
size_t nl = nl_len(&has_nl, line->ptr + no_nl, line->size - no_nl);
57-
double now = git__timer();
57+
uint64_t now = git_time_monotonic();
5858
size_t i;
5959

6060
/* Avoid spamming the console with progress updates */
@@ -191,20 +191,21 @@ static int fetch_receiving(
191191
{
192192
char *recv_units[] = { "B", "KiB", "MiB", "GiB", "TiB", NULL };
193193
char *rate_units[] = { "B/s", "KiB/s", "MiB/s", "GiB/s", "TiB/s", NULL };
194+
uint64_t now, elapsed;
194195

195-
double now, recv_len, rate, elapsed;
196+
double recv_len, rate;
196197
size_t recv_unit_idx = 0, rate_unit_idx = 0;
197198
bool done = (stats->received_objects == stats->total_objects);
198199

199200
if (!progress->action_start)
200-
progress->action_start = git__timer();
201+
progress->action_start = git_time_monotonic();
201202

202203
if (done && progress->action_finish)
203204
now = progress->action_finish;
204205
else if (done)
205-
progress->action_finish = now = git__timer();
206+
progress->action_finish = now = git_time_monotonic();
206207
else
207-
now = git__timer();
208+
now = git_time_monotonic();
208209

209210
if (progress->throughput_update &&
210211
now - progress->throughput_update < THROUGHPUT_UPDATE_TIME) {

src/cli/progress.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,19 +30,19 @@ typedef struct {
3030
cli_progress_t action;
3131

3232
/* Actions may time themselves (eg fetch) but are not required to */
33-
double action_start;
34-
double action_finish;
33+
uint64_t action_start;
34+
uint64_t action_finish;
3535

3636
/* Last console update, avoid too frequent updates. */
37-
double last_update;
37+
uint64_t last_update;
3838

3939
/* Accumulators for partial output and deferred updates. */
4040
git_str sideband;
4141
git_str onscreen;
4242
git_str deferred;
4343

4444
/* Last update about throughput */
45-
double throughput_update;
45+
uint64_t throughput_update;
4646
double throughput_bytes;
4747
} cli_progress;
4848

src/libgit2/pack-objects.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -255,10 +255,10 @@ int git_packbuilder_insert(git_packbuilder *pb, const git_oid *oid,
255255
pb->done = false;
256256

257257
if (pb->progress_cb) {
258-
double current_time = git__timer();
259-
double elapsed = current_time - pb->last_progress_report_time;
258+
uint64_t current_time = git_time_monotonic();
259+
uint64_t elapsed = current_time - pb->last_progress_report_time;
260260

261-
if (elapsed < 0 || elapsed >= MIN_PROGRESS_UPDATE_INTERVAL) {
261+
if (elapsed >= MIN_PROGRESS_UPDATE_INTERVAL) {
262262
pb->last_progress_report_time = current_time;
263263

264264
ret = pb->progress_cb(
@@ -934,10 +934,10 @@ static int report_delta_progress(
934934
int ret;
935935

936936
if (pb->progress_cb) {
937-
double current_time = git__timer();
938-
double elapsed = current_time - pb->last_progress_report_time;
937+
uint64_t current_time = git_time_monotonic();
938+
uint64_t elapsed = current_time - pb->last_progress_report_time;
939939

940-
if (force || elapsed < 0 || elapsed >= MIN_PROGRESS_UPDATE_INTERVAL) {
940+
if (force || elapsed >= MIN_PROGRESS_UPDATE_INTERVAL) {
941941
pb->last_progress_report_time = current_time;
942942

943943
ret = pb->progress_cb(

src/libgit2/pack-objects.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,9 @@ struct git_packbuilder {
9696

9797
git_packbuilder_progress progress_cb;
9898
void *progress_cb_payload;
99-
double last_progress_report_time; /* the time progress was last reported */
99+
100+
/* the time progress was last reported, in millisecond ticks */
101+
uint64_t last_progress_report_time;
100102

101103
bool done;
102104
};

src/libgit2/transports/smart_protocol.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1114,7 +1114,7 @@ struct push_packbuilder_payload
11141114
git_push_transfer_progress_cb cb;
11151115
void *cb_payload;
11161116
size_t last_bytes;
1117-
double last_progress_report_time;
1117+
uint64_t last_progress_report_time;
11181118
};
11191119

11201120
static int stream_thunk(void *buf, size_t size, void *data)
@@ -1126,11 +1126,11 @@ static int stream_thunk(void *buf, size_t size, void *data)
11261126
return error;
11271127

11281128
if (payload->cb) {
1129-
double current_time = git__timer();
1130-
double elapsed = current_time - payload->last_progress_report_time;
1129+
uint64_t current_time = git_time_monotonic();
1130+
uint64_t elapsed = current_time - payload->last_progress_report_time;
11311131
payload->last_bytes += size;
11321132

1133-
if (elapsed < 0 || elapsed >= MIN_PROGRESS_UPDATE_INTERVAL) {
1133+
if (elapsed >= MIN_PROGRESS_UPDATE_INTERVAL) {
11341134
payload->last_progress_report_time = current_time;
11351135
error = payload->cb(payload->pb->nr_written, payload->pb->nr_objects, payload->last_bytes, payload->cb_payload);
11361136
}

src/util/rand.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@ GIT_INLINE(int) getseed(uint64_t *seed)
3232
HCRYPTPROV provider;
3333
SYSTEMTIME systemtime;
3434
FILETIME filetime, idletime, kerneltime, usertime;
35-
bits convert;
3635

3736
if (CryptAcquireContext(&provider, 0, 0, PROV_RSA_FULL,
3837
CRYPT_VERIFYCONTEXT|CRYPT_SILENT)) {
@@ -67,7 +66,7 @@ GIT_INLINE(int) getseed(uint64_t *seed)
6766
*seed ^= ((uint64_t)GetCurrentProcessId() << 32);
6867
*seed ^= ((uint64_t)GetCurrentThreadId() << 48);
6968

70-
convert.f = git__timer(); *seed ^= (convert.d);
69+
*seed ^= git_time_monotonic();
7170

7271
/* Mix in the addresses of some functions and variables */
7372
*seed ^= (((uint64_t)((uintptr_t)seed) << 32));
@@ -82,9 +81,12 @@ GIT_INLINE(int) getseed(uint64_t *seed)
8281
{
8382
struct timeval tv;
8483
double loadavg[3];
85-
bits convert;
8684
int fd;
8785

86+
# if defined(GIT_RAND_GETLOADAVG)
87+
bits convert;
88+
# endif
89+
8890
# if defined(GIT_RAND_GETENTROPY)
8991
GIT_UNUSED((fd = 0));
9092

@@ -131,7 +133,7 @@ GIT_INLINE(int) getseed(uint64_t *seed)
131133
GIT_UNUSED(loadavg[0]);
132134
# endif
133135

134-
convert.f = git__timer(); *seed ^= (convert.d);
136+
*seed ^= git_time_monotonic();
135137

136138
/* Mix in the addresses of some variables */
137139
*seed ^= ((uint64_t)((size_t)((void *)seed)) << 32);

src/util/util.h

Lines changed: 24 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -319,59 +319,67 @@ GIT_INLINE(void) git__memzero(void *data, size_t size)
319319

320320
#ifdef GIT_WIN32
321321

322-
GIT_INLINE(double) git__timer(void)
322+
GIT_INLINE(uint64_t) git_time_monotonic(void)
323323
{
324324
/* GetTickCount64 returns the number of milliseconds that have
325325
* elapsed since the system was started. */
326-
return (double) GetTickCount64() / (double) 1000;
326+
return GetTickCount64();
327327
}
328328

329329
#elif __APPLE__
330330

331331
#include <mach/mach_time.h>
332+
#include <sys/time.h>
332333

333-
GIT_INLINE(double) git__timer(void)
334+
GIT_INLINE(uint64_t) git_time_monotonic(void)
334335
{
335-
uint64_t time = mach_absolute_time();
336-
static double scaling_factor = 0;
336+
static double scaling_factor = 0;
337+
338+
if (scaling_factor == 0) {
339+
mach_timebase_info_data_t info;
337340

338-
if (scaling_factor == 0) {
339-
mach_timebase_info_data_t info;
340-
(void)mach_timebase_info(&info);
341-
scaling_factor = (double)info.numer / (double)info.denom;
342-
}
341+
scaling_factor = mach_timebase_info(&info) == KERN_SUCCESS ?
342+
((double)info.numer / (double)info.denom) / 1.0E6 :
343+
-1;
344+
} else if (scaling_factor < 0) {
345+
struct timeval tv;
346+
347+
/* mach_timebase_info failed; fall back to gettimeofday */
348+
gettimeofday(&tv, NULL);
349+
return (tv.tv_sec * 1000) + (tv.tv_usec / 1000);
350+
}
343351

344-
return (double)time * scaling_factor / 1.0E9;
352+
return (uint64_t)(mach_absolute_time() * scaling_factor);
345353
}
346354

347355
#elif defined(__amigaos4__)
348356

349357
#include <proto/timer.h>
350358

351-
GIT_INLINE(double) git__timer(void)
359+
GIT_INLINE(uint64_t) git_time_monotonic(void)
352360
{
353361
struct TimeVal tv;
354362
ITimer->GetUpTime(&tv);
355-
return (double)tv.Seconds + (double)tv.Microseconds / 1.0E6;
363+
return (tv.Seconds * 1000) + (tv.Microseconds / 1000);
356364
}
357365

358366
#else
359367

360368
#include <sys/time.h>
361369

362-
GIT_INLINE(double) git__timer(void)
370+
GIT_INLINE(uint64_t) git_time_monotonic(void)
363371
{
364372
struct timeval tv;
365373

366374
#ifdef CLOCK_MONOTONIC
367375
struct timespec tp;
368376
if (clock_gettime(CLOCK_MONOTONIC, &tp) == 0)
369-
return (double) tp.tv_sec + (double) tp.tv_nsec / 1.0E9;
377+
return (tp.tv_sec * 1000) + (tp.tv_nsec / 1.0E6);
370378
#endif
371379

372380
/* Fall back to using gettimeofday */
373381
gettimeofday(&tv, NULL);
374-
return (double)tv.tv_sec + (double)tv.tv_usec / 1.0E6;
382+
return (tv.tv_sec * 1000) + (tv.tv_usec / 1000);
375383
}
376384

377385
#endif

tests/clar/clar_libgit2_timer.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,23 +8,23 @@ void cl_perf_timer__init(cl_perf_timer *t)
88

99
void cl_perf_timer__start(cl_perf_timer *t)
1010
{
11-
t->time_started = git__timer();
11+
t->time_started = git_time_monotonic();
1212
}
1313

1414
void cl_perf_timer__stop(cl_perf_timer *t)
1515
{
16-
double time_now = git__timer();
16+
uint64_t time_now = git_time_monotonic();
1717

1818
t->last = time_now - t->time_started;
1919
t->sum += t->last;
2020
}
2121

22-
double cl_perf_timer__last(const cl_perf_timer *t)
22+
uint64_t cl_perf_timer__last(const cl_perf_timer *t)
2323
{
2424
return t->last;
2525
}
2626

27-
double cl_perf_timer__sum(const cl_perf_timer *t)
27+
uint64_t cl_perf_timer__sum(const cl_perf_timer *t)
2828
{
2929
return t->sum;
3030
}

tests/clar/clar_libgit2_timer.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,13 @@
44
struct cl_perf_timer
55
{
66
/* cumulative running time across all start..stop intervals */
7-
double sum;
7+
uint64_t sum;
88

99
/* value of last start..stop interval */
10-
double last;
10+
uint64_t last;
1111

1212
/* clock value at start */
13-
double time_started;
13+
uint64_t time_started;
1414
};
1515

1616
#define CL_PERF_TIMER_INIT {0}
@@ -24,12 +24,12 @@ void cl_perf_timer__stop(cl_perf_timer *t);
2424
/**
2525
* return value of last start..stop interval in seconds.
2626
*/
27-
double cl_perf_timer__last(const cl_perf_timer *t);
27+
uint64_t cl_perf_timer__last(const cl_perf_timer *t);
2828

2929
/**
3030
* return cumulative running time across all start..stop
3131
* intervals in seconds.
3232
*/
33-
double cl_perf_timer__sum(const cl_perf_timer *t);
33+
uint64_t cl_perf_timer__sum(const cl_perf_timer *t);
3434

3535
#endif /* __CLAR_LIBGIT2_TIMER__ */

tests/clar/clar_libgit2_trace.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,7 @@ static void _cl_trace_cb__event_handler(
197197

198198
case CL_TRACE__TEST__END:
199199
cl_perf_timer__stop(&s_timer_test);
200-
git_trace(GIT_TRACE_TRACE, "%s::%s: End Test (%.3f %.3f)", suite_name, test_name,
200+
git_trace(GIT_TRACE_TRACE, "%s::%s: End Test (%" PRIuZ " %" PRIuZ ")", suite_name, test_name,
201201
cl_perf_timer__last(&s_timer_run),
202202
cl_perf_timer__last(&s_timer_test));
203203
break;

0 commit comments

Comments
 (0)