160 lines
4.6 KiB
C
160 lines
4.6 KiB
C
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <time.h>
|
|
#include <string.h>
|
|
#include <stdint.h>
|
|
|
|
#include "../src/vector.h"
|
|
#include "../src/map.h"
|
|
#include "../src/bigint.h"
|
|
|
|
typedef void (*test_fn_t)(size_t iterations);
|
|
|
|
void test_vector(size_t iterations) {
|
|
vector_t *vec = vector_new(16, sizeof(int)).value.vector;
|
|
|
|
for (size_t idx = 0; idx < iterations; idx++) {
|
|
vector_push(vec, &idx);
|
|
}
|
|
|
|
volatile uint64_t sum = 0; // prevent the compiler from optimizing away the sum
|
|
for (size_t idx = 0; idx < iterations; idx++) {
|
|
const int *val = (int*)vector_get(vec, idx).value.element;
|
|
sum += *val;
|
|
}
|
|
|
|
vector_destroy(vec);
|
|
}
|
|
|
|
void test_map(size_t iterations) {
|
|
map_t *map = map_new().value.map;
|
|
char key[64];
|
|
|
|
for (size_t idx = 0; idx < iterations; idx++) {
|
|
snprintf(key, sizeof(key), "key_%zu", idx);
|
|
|
|
int *value = malloc(sizeof(int));
|
|
*value = (int)idx;
|
|
|
|
map_add(map, key, (void*)value);
|
|
}
|
|
|
|
volatile uint64_t sum = 0; // prevent the compiler from optimizing away the sum
|
|
for (size_t idx = 0; idx < iterations; idx++) {
|
|
snprintf(key, sizeof(key), "key_%zu", idx);
|
|
|
|
const int *val = (const int*)map_get(map, key).value.element;
|
|
sum += *val;
|
|
}
|
|
|
|
// Cleanup values
|
|
for (size_t idx = 0; idx < map->capacity; idx++) {
|
|
snprintf(key, sizeof(key), "key_%zu", idx);
|
|
|
|
int *val = (int *)map_get(map, key).value.element;
|
|
free(val);
|
|
|
|
map_remove(map, key);
|
|
}
|
|
|
|
map_destroy(map);
|
|
}
|
|
|
|
void test_bigint(size_t iterations) {
|
|
volatile uint64_t accumulator = 0;
|
|
|
|
for (size_t idx = 1; idx <= iterations; idx++) {
|
|
long long a_val = (long long)idx * 123456789LL;
|
|
long long b_val = (long long)idx * 17777LL;
|
|
|
|
bigint_result_t a_res = bigint_from_int(a_val);
|
|
bigint_result_t b_res = bigint_from_int(b_val);
|
|
|
|
if (a_res.status != BIGINT_OK || b_res.status != BIGINT_OK) {
|
|
bigint_destroy(a_res.value.number);
|
|
bigint_destroy(b_res.value.number);
|
|
continue;
|
|
}
|
|
|
|
bigint_t *a = a_res.value.number;
|
|
bigint_t *b = b_res.value.number;
|
|
|
|
// Addition
|
|
bigint_result_t add_res = bigint_add(a, b);
|
|
if (add_res.status == BIGINT_OK) {
|
|
vector_result_t v = vector_get(add_res.value.number->digits, 0);
|
|
if (v.status == VECTOR_OK) { accumulator += *(int *)v.value.element; }
|
|
bigint_destroy(add_res.value.number);
|
|
}
|
|
|
|
// Substraction
|
|
bigint_result_t sub_res = bigint_sub(a, b);
|
|
if (sub_res.status == BIGINT_OK) {
|
|
vector_result_t v = vector_get(sub_res.value.number->digits, 0);
|
|
if (v.status == VECTOR_OK) { accumulator += *(int *)v.value.element; }
|
|
bigint_destroy(sub_res.value.number);
|
|
}
|
|
|
|
// Multiplication
|
|
bigint_result_t mul_res = bigint_prod(a, b);
|
|
if (mul_res.status == BIGINT_OK) {
|
|
vector_result_t v = vector_get(mul_res.value.number->digits, 0);
|
|
if (v.status == VECTOR_OK) { accumulator += *(int *)v.value.element; }
|
|
bigint_destroy(mul_res.value.number);
|
|
}
|
|
|
|
// Division
|
|
bigint_result_t div_res = bigint_divmod(a, b);
|
|
if (div_res.status == BIGINT_OK) {
|
|
vector_result_t v = vector_get(div_res.value.division.quotient->digits, 0);
|
|
if (v.status == VECTOR_OK) { accumulator += *(int *)v.value.element; }
|
|
bigint_destroy(div_res.value.division.quotient);
|
|
bigint_destroy(div_res.value.division.remainder);
|
|
}
|
|
|
|
bigint_destroy(a); bigint_destroy(b);
|
|
}
|
|
}
|
|
|
|
static inline uint64_t now_ns(void) {
|
|
struct timespec ts;
|
|
clock_gettime(CLOCK_MONOTONIC, &ts);
|
|
|
|
return (uint64_t)ts.tv_sec * 1000000000ULL + ts.tv_nsec;
|
|
}
|
|
|
|
long long benchmark(test_fn_t fun, size_t iterations, size_t runs) {
|
|
long long total = 0;
|
|
|
|
for (size_t idx = 0; idx < runs; idx++) {
|
|
uint64_t start = now_ns();
|
|
fun(iterations);
|
|
uint64_t end = now_ns();
|
|
|
|
total += (end - start);
|
|
}
|
|
|
|
return (long long)(total / runs / 1000000);
|
|
}
|
|
|
|
int main(void) {
|
|
// Do a warmup run
|
|
test_vector(1000);
|
|
test_map(1000);
|
|
test_bigint(1000);
|
|
|
|
printf("Computing Vector average time...");
|
|
fflush(stdout);
|
|
printf("average time: %lld ms\n", benchmark(test_vector, 1e6, 30));
|
|
|
|
printf("Computing Map average time...");
|
|
fflush(stdout);
|
|
printf("average time: %lld ms\n", benchmark(test_map, 1e5, 30));
|
|
|
|
printf("Computing BigInt average time...");
|
|
fflush(stdout);
|
|
printf("average time: %lld ms\n", benchmark(test_bigint, 1e5, 30));
|
|
|
|
return 0;
|
|
}
|