#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <time.h>
#include "../include/fastnet.h"
#define ITERATIONS 100000
#define STATE_SIZE 512
static inline uint64_t get_nanos() {
struct timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts);
return (uint64_t)ts.tv_sec * 1000000000ULL + ts.tv_nsec;
}
int main() {
printf("╔═══════════════════════════════════════╗\n");
printf("║ FastNet FFI Delta Benchmark ║\n");
printf("╠═══════════════════════════════════════╣\n");
printf("║ Iterations: %d ║\n", ITERATIONS);
printf("║ State Size: %d bytes ║\n", STATE_SIZE);
printf("╚═══════════════════════════════════════╝\n\n");
FastNetDeltaEncoder encoder = fastnet_delta_encoder_create();
FastNetDeltaDecoder decoder = fastnet_delta_decoder_create();
if (!encoder || !decoder) {
printf("ERROR: Failed to create encoder/decoder\n");
return 1;
}
uint8_t old_state[STATE_SIZE];
uint8_t new_state[STATE_SIZE];
uint8_t delta[1024];
uint8_t reconstructed[STATE_SIZE];
uint32_t delta_len;
for (int i = 0; i < STATE_SIZE; i++) {
old_state[i] = (uint8_t)(i % 256);
new_state[i] = (uint8_t)(i % 256);
}
new_state[0] = 100; new_state[4] = 150; new_state[8] = 75;
uint64_t encode_times[ITERATIONS];
uint64_t decode_times[ITERATIONS];
int encode_failures = 0;
int decode_failures = 0;
uint64_t total_delta_size = 0;
printf("Running benchmark...\n");
for (int i = 0; i < ITERATIONS; i++) {
new_state[0] = (uint8_t)(100 + (i % 50));
uint64_t start = get_nanos();
int result = fastnet_delta_encode(encoder, old_state, STATE_SIZE,
new_state, STATE_SIZE,
delta, sizeof(delta), &delta_len);
uint64_t end = get_nanos();
if (result == 0) {
encode_times[i - encode_failures] = end - start;
total_delta_size += delta_len;
} else {
encode_failures++;
}
if (i % 20000 == 0 && i > 0) {
printf(" Progress: %d/%d\n", i, ITERATIONS);
}
}
new_state[0] = 100;
fastnet_delta_encode(encoder, old_state, STATE_SIZE, new_state, STATE_SIZE,
delta, sizeof(delta), &delta_len);
for (int i = 0; i < ITERATIONS; i++) {
memcpy(reconstructed, old_state, STATE_SIZE);
uint64_t start = get_nanos();
int result = fastnet_delta_apply(decoder, delta, delta_len,
reconstructed, STATE_SIZE);
uint64_t end = get_nanos();
if (result == 0) {
decode_times[i - decode_failures] = end - start;
} else {
decode_failures++;
}
}
int valid_encodes = ITERATIONS - encode_failures;
int valid_decodes = ITERATIONS - decode_failures;
for (int i = 0; i < valid_encodes - 1; i++) {
for (int j = i + 1; j < valid_encodes; j++) {
if (encode_times[i] > encode_times[j]) {
uint64_t tmp = encode_times[i];
encode_times[i] = encode_times[j];
encode_times[j] = tmp;
}
}
}
for (int i = 0; i < valid_decodes - 1; i++) {
for (int j = i + 1; j < valid_decodes; j++) {
if (decode_times[i] > decode_times[j]) {
uint64_t tmp = decode_times[i];
decode_times[i] = decode_times[j];
decode_times[j] = tmp;
}
}
}
uint64_t encode_sum = 0;
for (int i = 0; i < valid_encodes; i++) encode_sum += encode_times[i];
uint64_t decode_sum = 0;
for (int i = 0; i < valid_decodes; i++) decode_sum += decode_times[i];
printf("\n┌─────────────────────────────────────────┐\n");
printf("│ Encode Results │\n");
printf("├─────────────────────────────────────────┤\n");
printf("│ Min: %8.3f ns │\n", (double)encode_times[0]);
printf("│ Avg: %8.3f ns │\n", (double)encode_sum / valid_encodes);
printf("│ Median: %8.3f ns │\n", (double)encode_times[valid_encodes/2]);
printf("│ P99: %8.3f ns │\n", (double)encode_times[(int)(valid_encodes * 0.99)]);
printf("│ Max: %8.3f ns │\n", (double)encode_times[valid_encodes-1]);
printf("│ Failures: %d │\n", encode_failures);
printf("└─────────────────────────────────────────┘\n");
printf("\n┌─────────────────────────────────────────┐\n");
printf("│ Decode Results │\n");
printf("├─────────────────────────────────────────┤\n");
printf("│ Min: %8.3f ns │\n", (double)decode_times[0]);
printf("│ Avg: %8.3f ns │\n", (double)decode_sum / valid_decodes);
printf("│ Median: %8.3f ns │\n", (double)decode_times[valid_decodes/2]);
printf("│ P99: %8.3f ns │\n", (double)decode_times[(int)(valid_decodes * 0.99)]);
printf("│ Max: %8.3f ns │\n", (double)decode_times[valid_decodes-1]);
printf("│ Failures: %d │\n", decode_failures);
printf("└─────────────────────────────────────────┘\n");
printf("\n┌─────────────────────────────────────────┐\n");
printf("│ Compression Stats │\n");
printf("├─────────────────────────────────────────┤\n");
printf("│ Original: %d bytes │\n", STATE_SIZE);
printf("│ Avg Delta: %.1f bytes │\n", (double)total_delta_size / valid_encodes);
printf("│ Compression: %.1f%% │\n",
(1.0 - (double)total_delta_size / valid_encodes / STATE_SIZE) * 100.0);
printf("└─────────────────────────────────────────┘\n");
double encode_avg_ns = (double)encode_sum / valid_encodes;
double decode_avg_ns = (double)decode_sum / valid_decodes;
double encode_ops_per_sec = 1000000000.0 / encode_avg_ns;
double decode_ops_per_sec = 1000000000.0 / decode_avg_ns;
printf("\n┌─────────────────────────────────────────┐\n");
printf("│ Throughput │\n");
printf("├─────────────────────────────────────────┤\n");
printf("│ Encode: %.0f ops/sec │\n", encode_ops_per_sec);
printf("│ Decode: %.0f ops/sec │\n", decode_ops_per_sec);
printf("└─────────────────────────────────────────┘\n");
fastnet_delta_encoder_destroy(encoder);
fastnet_delta_decoder_destroy(decoder);
return 0;
}