#include #include #include #include #include #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; }