aboutsummaryrefslogtreecommitdiff
path: root/main.c
blob: 93fd408aad543c979e774d99b3b78a11a45201bc (plain) (blame)
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

#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <time.h>

#include "src/std/assert.h"
#include "src/json/json.h"
#include "src/std/memory.h"
#include "src/std/testing.h"
#include "src/std/types.h"
#include "src/std/vec.h"

// Get high resolution time in nanoseconds
double get_time_ns(void) {
    struct timespec ts;
    clock_gettime(CLOCK_MONOTONIC, &ts);
    return ts.tv_sec * 1000000000.0 + ts.tv_nsec;
}

void run_benchmark(const char *filename, i32 iterations) {
    Arena perm = Arena_new(1e9);
    printf("Loading file: %s\n", filename);

    MemoryFile file = load_file(&perm, filename);

    printf("File size: %zu bytes\n", file.size);
    printf("Running %d iterations...\n\n", iterations);

    // Statistics tracking
    f32 timings[iterations];
    f32 timing_avg = 0.0;

    Arena tmp = Arena_new(8e9);

    printf("Benchmarking...\n");
    for (i32 i = 0; i < iterations; i++) {
        Arena_reset(&tmp);
        size used = Arena_get_used(tmp);
        double start_time = get_time_ns();
        JSON_parse(&tmp, file.content, file.size);
        double end_time = get_time_ns();

        timings[i] = end_time - start_time;
        timing_avg += timings[i];

        size new_used = Arena_get_used(tmp);
        size allocated = new_used - used;
        printf("Iteration %d: %3.f ms\t%td MB\n", i + 1, timings[i] / 1000000,
               allocated / 1024 / 1024);

        if ((i + 1) % 100 == 0) {
            printf("Completed %d/%d iterations\n", i + 1, iterations);
        }
    }

    // Calculate statistics
    timing_avg /= iterations;
    f32 timing_var = 0.0;
    for (i32 i = 0; i < iterations; i++) {
        timing_var += (timings[i] - timing_avg) * (timings[i] - timing_avg);
    }
    timing_var /= iterations;
    f32 timing_stddev = sqrt(timing_var);
    double avg_throughput_mb_s =
        (file.size / (1024.0 * 1024.0)) / (timing_avg / 1000000000.0);

    printf("\n=== Benchmark Results ===\n");
    printf("%3.f ms ± %3.f ms per loop (mean ± std. dev. of %d runs, 1 loop "
           "each)\n",
           timing_avg / 1000000, timing_stddev / 1000000, iterations);
    printf("Throughput: %.2f MB/s\n", avg_throughput_mb_s);
}

i32 main(i32 argc, char *argv[]) {
    char *filename = "";
    // Parse command line arguments
    assert(argc == 3, "main <file.json> <iterations>");
    filename = argv[1];
    i32 iterations = atoi(argv[2]);
    if (iterations <= 0) {
        fprintf(stderr, "Error: Invalid number of iterations\n");
        return 1;
    }

    printf("JSON Parser Benchmark\n");
    printf("====================\n");

    run_benchmark(filename, iterations);

    return 0;
}