aboutsummaryrefslogtreecommitdiff
path: root/main.c
blob: 01df170527df27ea526b4e9452266bb469cfa101 (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
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

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

#include "include/json.h"
#include "include/memory.h"
#include "include/types.h"

// Load entire file into memory
byte *load_file(const char *filename, size *file_size) {
    FILE *file = fopen(filename, "rb");
    if (!file) {
        fprintf(stderr, "Error: Could not open file '%s'\n", filename);
        return NULL;
    }

    // Get file size
    fseek(file, 0, SEEK_END);
    *file_size = ftell(file);
    fseek(file, 0, SEEK_SET);

    // Allocate buffer and read file
    byte *buffer = malloc(*file_size + 1);
    if (!buffer) {
        fprintf(stderr, "Error: Could not allocate memory for file\n");
        fclose(file);
        return NULL;
    }

    size bytes_read = fread(buffer, 1, *file_size, file);
    if (bytes_read != *file_size) {
        fprintf(stderr, "Error: Could not read entire file\n");
        free(buffer);
        fclose(file);
        return NULL;
    }

    buffer[*file_size] = '\0'; // Null terminate
    fclose(file);
    return buffer;
}

// 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) {
    printf("Loading file: %s\n", filename);

    size file_size;
    byte *content = load_file(filename, &file_size);
    if (!content) return;

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

    // Statistics tracking
    double total_time = 0.0;
    double min_time = 1e9;
    double max_time = 0.0;

    Arena arena = Arena_new(8e9);

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

        double elapsed = end_time - start_time;
        total_time += elapsed;

        if (elapsed < min_time) min_time = elapsed;
        if (elapsed > max_time) max_time = elapsed;

        size new_used = Arena_get_used(arena);
        size allocated = new_used - used;
        printf("Iteration %d: %td MB allocated\n", i + 1,
               allocated / 1024 / 1024);

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

    // Calculate statistics
    double avg_time = total_time / iterations;
    double avg_time_ms = avg_time / 1000000.0;
    double min_time_ms = min_time / 1000000.0;
    double max_time_ms = max_time / 1000000.0;

    // Calculate throughput
    double avg_throughput_mb_s =
        (file_size / (1024.0 * 1024.0)) / (avg_time / 1000000000.0);

    printf("\n=== Benchmark Results ===\n");
    printf("Iterations:     %d\n", iterations);
    printf("File size:      %zu bytes (%.2f MB)\n", file_size,
           file_size / (1024.0 * 1024.0));
    printf("\nTiming (milliseconds):\n");
    printf("  Average:      %.3f ms\n", avg_time_ms);
    printf("  Minimum:      %.3f ms\n", min_time_ms);
    printf("  Maximum:      %.3f ms\n", max_time_ms);
    printf("  Range:        %.3f ms\n", max_time_ms - min_time_ms);
    printf("\nThroughput:\n");
    printf("  Average:      %.2f MB/s\n", avg_throughput_mb_s);
    printf("  Parse rate:   %.0f parses/second\n", 1000.0 / avg_time_ms);
}

i32 main(i32 argc, char *argv[]) {
    const char *filename = "out.json";
    i32 iterations = 7;

    // Parse command line arguments
    if (argc >= 2) {
        filename = argv[1];
    }
    if (argc >= 3) {
        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;
}