File: bench.c

package info (click to toggle)
libxkbcommon 1.13.1-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 8,344 kB
  • sloc: ansic: 57,807; xml: 8,905; python: 7,451; yacc: 913; sh: 253; makefile: 23
file content (159 lines) | stat: -rw-r--r-- 3,831 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
/*
 * Copyright © 2015 Kazunobu Kuriyama <kazunobu.kuriyama@nifty.com>
 * Copyright © 2015 Ran Benita <ran234@gmail.com>
 * SPDX-License-Identifier: MIT
 */

#include "config.h"

#include <assert.h>
#include <stdio.h>
#include <math.h>

#include "bench.h"
#include "../src/utils.h"

#ifndef _WIN32
#include <time.h>
#include <sys/time.h>
#else
#include <windows.h>
#include <stdint.h>

struct timeval {
    long tv_sec, tv_usec;
};

static int
gettimeofday(struct timeval *tv, void *unused)
{
    static const uint64_t EPOCH = ((uint64_t) 116444736000000000ULL);

    SYSTEMTIME system_time;
    FILETIME file_time;
    uint64_t t;

    GetSystemTime(&system_time);
    SystemTimeToFileTime(&system_time, &file_time);
    t = (uint64_t) file_time.dwLowDateTime;
    t += ((uint64_t) file_time.dwHighDateTime) << 32;

    tv->tv_sec  = (long) ((t - EPOCH) / 10000000L);
    tv->tv_usec = (long) (system_time.wMilliseconds * 1000);
    return 0;
}
#endif

void
bench_start(struct bench *bench)
{
    struct timeval val;
    (void) gettimeofday(&val, NULL);
    bench->start = (struct bench_time) {
        .seconds = val.tv_sec,
        .nanoseconds = val.tv_usec * 1000,
    };
}

void
bench_stop(struct bench *bench)
{
    struct timeval val;
    (void) gettimeofday(&val, NULL);
    bench->stop = (struct bench_time) {
        .seconds = val.tv_sec,
        .nanoseconds = val.tv_usec * 1000,
    };
}

#ifndef _WIN32
void
bench_start2(struct bench *bench)
{
    struct timespec t;
	(void) clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &t);
	// (void) clock_gettime(CLOCK_MONOTONIC, &t);
    bench->start = (struct bench_time) {
        .seconds = t.tv_sec,
        .nanoseconds = t.tv_nsec,
    };
}

void
bench_stop2(struct bench *bench)
{
    struct timespec t;
	(void) clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &t);
	// (void) clock_gettime(CLOCK_MONOTONIC, &t);
    bench->stop = (struct bench_time) {
        .seconds = t.tv_sec,
        .nanoseconds = t.tv_nsec,
    };
}
#endif

void
bench_elapsed(const struct bench *bench, struct bench_time *result)
{
    result->seconds = bench->stop.seconds - bench->start.seconds;
    result->nanoseconds = bench->stop.nanoseconds - bench->start.nanoseconds;
    if (result->nanoseconds < 0) {
        result->nanoseconds += 1000000000;
        result->seconds--;
    }
}

char *
bench_elapsed_str(const struct bench *bench)
{
    struct bench_time elapsed;
    char *buf;
    int ret;

    bench_elapsed(bench, &elapsed);
    ret = asprintf(&buf, "%ld.%06ld", elapsed.seconds, elapsed.nanoseconds / 1000);
    assert(ret >= 0);

    return buf;
}

/* Utils for bench method adapted from: https://hackage.haskell.org/package/tasty-bench */

#define fit(x1, x2) ((x1) / 5 + 2 * ((x2) / 5))
#define sqr(x) ((x) * (x))

static void
predict(long long t1, long long t2, struct estimate *est)
{
    const long long t = fit(t1, t2);
    est->elapsed = t;
    est->stdev =
        llroundl(sqrtl((long double)sqr(t1 - t) + (long double)sqr(t2 - 2 * t)));
}

#define high(t, prec) ((t) + (prec))
#define low(t, prec) ((t) - (prec))
#define MIN_PRECISION 1000000 /* 1ms */

void
predictPerturbed(const struct bench_time *b1, const struct bench_time *b2,
                 struct estimate *est)
{
    const long long t1 = bench_time_elapsed_nanoseconds(b1);
    const long long t2 = bench_time_elapsed_nanoseconds(b2);

#ifndef _WIN32
    struct timespec ts;
    (void) clock_getres(CLOCK_PROCESS_CPUTIME_ID, &ts);
    long long precision = MAX(ts.tv_sec * 1000000000 + ts.tv_nsec, MIN_PRECISION);
#else
    long long precision = MIN_PRECISION;
#endif

    struct estimate est1;
    struct estimate est2;
    predict(t1, t2, est);
    predict(low(t1, precision), high(t2, precision), &est1);
    predict(high(t1, precision), low(t2, precision), &est2);
    est->stdev = MAX(est1.stdev, est2.stdev);
}