Move benchmark scoring to the server

This commit is contained in:
2026-07-19 19:22:21 -05:00
parent 290344ae5b
commit 59b158b1c9
2 changed files with 44 additions and 108 deletions
+22 -88
View File
@@ -4,7 +4,6 @@
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <math.h>
#include <pthread.h>
#include <unistd.h>
#include <ctype.h>
@@ -30,7 +29,7 @@
#ifndef FB_API_BASE_URL
# define FB_API_BASE_URL "http://fossbench.net"
#endif
#define FB_VERSION "0.2.2"
#define FB_VERSION "0.3.0"
#if defined(__aarch64__) || defined(__arm64__) || defined(_M_ARM64)
# define D_INT "64-bit ALU: madd, umulh, udiv, bitops"
@@ -136,36 +135,6 @@ extern uint64_t fb_chase(void **ptrs, uint64_t steps);
# define REPEATS 3 /* Number of tries. */
#endif
/* Numbers used to calculate scores. */
#define FB_TARGET_SCORE 10000.0 /* reference-machine overall. */
/* Rates from the reference machine. */
#define FB_REF_INT 3086.0 /* Reference rate. */
#define FB_REF_INT32 3086.0 /* Common 32-bit integer reference. */
#define FB_REF_FP 1682.0 /* Reference rate. */
#define FB_REF_PRIMES 812.0 /* Reference rate. */
#define FB_REF_SIMD 6576.0 /* Reference rate. */
#define FB_REF_COMPRESS 674.0 /* Reference rate. */
#define FB_REF_CRYPTO 406.0 /* Reference rate. */
#define FB_REF_PHYSICS 631.0 /* Reference rate. */
#define FB_REF_SORT 363.0 /* Reference rate. */
#define FB_REF_CHASE 79.0 /* Memory test reference. */
#define FB_REF_STREAM 3200.0 /* STREAM triad reference rate. */
/* How much each test counts. */
#define FB_WEIGHT_INT 3.0 /* Wide integer mix. */
#define FB_WEIGHT_INT32 10.0 /* Common native-width integer work. */
#define FB_WEIGHT_CHASE 10.0 /* Random-access latency. */
#define FB_WEIGHT_STREAM 15.0 /* Sustained memory bandwidth. */
#define FB_WEIGHT_COMPRESS 12.0 /* Score weight. */
#define FB_WEIGHT_SORT 8.0 /* Score weight. */
#define FB_WEIGHT_SIMD 16.0 /* Vector and packed arithmetic. */
#define FB_WEIGHT_FP 10.0 /* Score weight. */
#define FB_WEIGHT_CRYPTO 8.0 /* Score weight. */
#define FB_WEIGHT_PRIMES 5.0 /* Score weight. */
#define FB_WEIGHT_PHYSICS 3.0 /* Divide/square-root-heavy. */
/* Simple repeatable random numbers. */
static uint64_t rng_state = 0x853c49e6748fea9bULL;
@@ -464,10 +433,8 @@ struct test {
const char *detail;
run_fn run;
uint64_t start_n;
double work_per_n; /* Amount of work used for scoring. */
double work_per_n; /* Amount of work used to calculate the raw rate. */
const char *unit;
double ref_rate; /* Rate used as the score reference. */
double weight; /* How much this test counts. */
};
static uint64_t run_int(uint64_t n, struct workspace *ws)
@@ -566,45 +533,33 @@ static uint64_t run_stream(uint64_t n, struct workspace *ws)
static const struct test tests[] = {
{ "Native Integer Math", "common 32-bit multiply/add/rotate mix",
run_int32, 20, 100000.0 * 16, "Mops/s",
FB_REF_INT32, FB_WEIGHT_INT32 },
run_int32, 20, 100000.0 * 16, "Mops/s" },
{ "Wide Integer Math", D_INT,
run_int, 20, 100000.0 * 24, "Mops/s",
FB_REF_INT, FB_WEIGHT_INT },
run_int, 20, 100000.0 * 24, "Mops/s" },
{ "Floating Point Math", D_FP,
run_fp, 20, 100000.0 * 20, "Mops/s",
FB_REF_FP, FB_WEIGHT_FP },
run_fp, 20, 100000.0 * 20, "Mops/s" },
{ "Prime Numbers", "sieve of Eratosthenes to 2M",
run_primes, 1, (double)PRIME_LIMIT, "Mcand/s",
FB_REF_PRIMES, FB_WEIGHT_PRIMES },
run_primes, 1, (double)PRIME_LIMIT, "Mcand/s" },
{ "Extended Instructions",D_SIMD,
run_simd, 10, 100000.0 * 32, "Mops/s",
FB_REF_SIMD, FB_WEIGHT_SIMD },
run_simd, 10, 100000.0 * 32, "Mops/s" },
{ "Compression", "LZ77 match finder, 4 MiB corpus",
run_compress, 1, (double)COMPRESS_LEN, "MB/s",
FB_REF_COMPRESS, FB_WEIGHT_COMPRESS },
run_compress, 1, (double)COMPRESS_LEN, "MB/s" },
{ "Encryption", "ChaCha20, 20 rounds, 1 MiB",
run_crypto, 4, (double)CIPHER_LEN, "MB/s",
FB_REF_CRYPTO, FB_WEIGHT_CRYPTO },
run_crypto, 4, (double)CIPHER_LEN, "MB/s" },
{ "Physics", "512-body direct-sum gravity",
run_physics, 4, (double)NBODY_N * NBODY_N, "Mpair/s",
FB_REF_PHYSICS, FB_WEIGHT_PHYSICS },
run_physics, 4, (double)NBODY_N * NBODY_N, "Mpair/s" },
{ "Sorting", "heapsort, 1M uint32",
run_sort, 1, (double)SORT_N * 20, "Mkey-cmp/s",
FB_REF_SORT, FB_WEIGHT_SORT },
run_sort, 1, (double)SORT_N * 20, "Mkey-cmp/s" },
{ "Memory Latency", CHASE_DETAIL,
run_chase, 1, 1000000.0, "ns/access",
FB_REF_CHASE, FB_WEIGHT_CHASE },
run_chase, 1, 1000000.0, "ns/access" },
{ "Memory Bandwidth", "STREAM triad, 12 MiB working set per thread",
run_stream, 16, (double)STREAM_N * 12.0, "MB/s",
FB_REF_STREAM, FB_WEIGHT_STREAM },
run_stream, 16, (double)STREAM_N * 12.0, "MB/s" },
};
#define NTESTS (sizeof(tests) / sizeof(tests[0]))
struct result {
double rate; /* Measured speed. */
double score;
uint64_t checksum;
double seconds;
uint64_t iters;
@@ -712,8 +667,6 @@ static struct result run_test(const struct test *t, int threads)
r.threads = threads;
/* Calculate the total speed. */
r.rate = ((double)threads * (double)n * t->work_per_n) / best / 1e6;
/* Turn the speed into a score. */
r.score = FB_TARGET_SCORE * (r.rate / t->ref_rate);
return r;
}
@@ -745,8 +698,8 @@ static void print_header(const struct system_info *info)
printf(" kernel: %s\n", info->kernel[0] ? info->kernel : "unknown");
printf(" compiler: %s\n", info->compiler);
printf("\n");
printf(" %-24s %12s %-11s %8s %9s\n",
"TEST", "RATE", "UNIT", "TIME", "SCORE");
printf(" %-24s %12s %-11s %8s\n",
"TEST", "RATE", "UNIT", "TIME");
printf(" --------------------------------------------------------------------------\n");
fflush(stdout);
}
@@ -756,9 +709,7 @@ int fossbench_run(int verbose, int upload_mode, int system_check)
struct result multi[NTESTS], single[NTESTS];
struct system_info system_info;
struct background_metrics background;
double multi_log_sum = 0.0, single_log_sum = 0.0;
double weight_sum = 0.0;
double benchmark_started, multicore_score, singlecore_score;
double benchmark_started;
uint64_t duration_ms;
size_t i;
@@ -788,8 +739,6 @@ int fossbench_run(int verbose, int upload_mode, int system_check)
print_header(&system_info);
for (i = 0; i < NTESTS; i++) {
double sm, ss;
printf(" %-24s", tests[i].name);
fflush(stdout);
@@ -797,35 +746,21 @@ int fossbench_run(int verbose, int upload_mode, int system_check)
multi[i] = run_test(&tests[i], (int)g_ncores);
single[i] = run_test(&tests[i], 1);
printf(" %12.1f %-11s %7.2fs %9.0f\n",
printf(" %12.1f %-11s %7.2fs\n",
display_metric(&tests[i], &multi[i]), tests[i].unit,
multi[i].seconds, multi[i].score);
multi[i].seconds);
if (verbose)
printf(" %-24s %s\n"
" %-24s weight=%.0f%% 1-core: %.1f %s / %.0f %ld-core: %.1f %s / %.0f\n",
"", tests[i].detail, "", tests[i].weight,
" %-24s 1-core: %.1f %s %ld-core: %.1f %s\n",
"", tests[i].detail, "",
display_metric(&tests[i], &single[i]), tests[i].unit,
single[i].score, g_ncores,
display_metric(&tests[i], &multi[i]), tests[i].unit,
multi[i].score);
g_ncores, display_metric(&tests[i], &multi[i]), tests[i].unit);
fflush(stdout);
/* Add this test to both total scores. */
sm = multi[i].score > 0.0 ? multi[i].score : 1e-9;
ss = single[i].score > 0.0 ? single[i].score : 1e-9;
multi_log_sum += tests[i].weight * log(sm);
single_log_sum += tests[i].weight * log(ss);
weight_sum += tests[i].weight;
}
printf(" --------------------------------------------------------------------------\n");
/* Add this test to both total scores. */
multicore_score = exp(multi_log_sum / weight_sum);
singlecore_score = exp(single_log_sum / weight_sum);
duration_ms = (uint64_t)((now_seconds() - benchmark_started) * 1000.0);
printf(" %-24s %44.0f\n", "MULTICORE SCORE", multicore_score);
printf(" %-24s %44.0f\n", "SINGLECORE SCORE", singlecore_score);
printf(" %-24s %41.2fs\n", "TOTAL DURATION", (double)duration_ms / 1000.0);
printf("\n");
@@ -853,8 +788,7 @@ int fossbench_run(int verbose, int upload_mode, int system_check)
#if defined(FB_NO_UPLOAD)
fprintf(stderr, " Upload support is disabled in this build.\n");
#else
upload_results(&system_info, multicore_score, singlecore_score,
multi, single, duration_ms, &background);
upload_results(&system_info, multi, single, duration_ms, &background);
#endif
}
}
+22 -20
View File
@@ -120,13 +120,13 @@ done:
}
#endif
static int upload_results(const struct system_info *info, double score,
double singlecore_score, const struct result *multi,
static int upload_results(const struct system_info *info,
const struct result *multi,
const struct result *single, uint64_t duration_ms,
const struct background_metrics *background)
{
char host[256], port[16], path[512], payload[16384];
char auth_header[600], response_body[2048], claim_url[1024];
char auth_header[600], response_body[2048], claim_url[1024], result_url[1024];
char cpu[512], model[512], os[512], compiler[256], kernel[256];
const char *base = FB_API_BASE_URL, *p, *slash, *colon;
int status = 0, payload_len;
@@ -168,16 +168,14 @@ static int upload_results(const struct system_info *info, double score,
payload_len = snprintf(payload, sizeof(payload),
"{\"cpu\":\"%s\",\"model\":\"%s\",\"cpu_cores\":%ld,\"cpu_threads\":%ld,"
"\"memory_mb\":%ld,\"operating_system\":\"%s\",\"compiler\":\"%s\","
"\"fossmark_version\":\"%s\",\"score\":%.17g,\"duration_ms\":%llu,"
"\"score_details\":{\"scoring_method\":\"weighted_geometric_mean\","
"\"target_score\":%.17g,\"multicore_score\":%.17g,\"singlecore_score\":%.17g,"
"\"fossmark_version\":\"%s\",\"workload_suite\":\"fossbench-cpu-v1\","
"\"duration_ms\":%llu,\"score_details\":{"
"\"minimum_test_seconds\":%.17g,\"repeats\":%d,"
"\"system_environment\":{\"kernel\":\"%s\",\"sample_seconds\":%d,"
"\"background_cpu_average_percent\":%.17g,\"background_cpu_peak_percent\":%.17g,"
"\"available_memory_mb\":%ld,\"process_count\":%ld},\"tests\":[",
cpu, model, info->cpu_cores, info->cpu_threads, info->memory_mb, os, compiler,
FB_VERSION, score, (unsigned long long)duration_ms, FB_TARGET_SCORE, score,
singlecore_score, MIN_SECONDS, REPEATS, kernel, background->samples,
FB_VERSION, (unsigned long long)duration_ms, MIN_SECONDS, REPEATS, kernel, background->samples,
background->average_cpu_percent, background->peak_cpu_percent,
background->available_memory_mb, background->process_count);
if (payload_len < 0 || (size_t)payload_len >= sizeof(payload)) return 0;
@@ -185,21 +183,24 @@ static int upload_results(const struct system_info *info, double score,
size_t used = (size_t)payload_len;
size_t i;
for (i = 0; i < NTESTS; i++) {
static const char *ids[] = {
"native_integer", "wide_integer", "floating_point", "primes",
"extended_instructions", "compression", "encryption", "physics",
"sorting", "memory_latency", "memory_bandwidth"
};
int n = snprintf(payload + used, sizeof(payload) - used,
"%s{\"name\":\"%s\",\"detail\":\"%s\",\"unit\":\"%s\","
"%s{\"id\":\"%s\",\"name\":\"%s\",\"detail\":\"%s\",\"unit\":\"%s\","
"\"start_iterations\":%llu,\"work_per_iteration\":%.17g,"
"\"reference_rate\":%.17g,\"weight\":%.17g,"
"\"multicore\":{\"display_metric\":%.17g,\"rate\":%.17g,\"score\":%.17g,"
"\"multicore\":{\"display_metric\":%.17g,\"rate\":%.17g,"
"\"seconds\":%.17g,\"iterations\":%llu,\"threads\":%d,\"checksum\":\"%llu\"},"
"\"singlecore\":{\"display_metric\":%.17g,\"rate\":%.17g,\"score\":%.17g,"
"\"singlecore\":{\"display_metric\":%.17g,\"rate\":%.17g,"
"\"seconds\":%.17g,\"iterations\":%llu,\"threads\":%d,\"checksum\":\"%llu\"}}",
i ? "," : "", tests[i].name, tests[i].detail, tests[i].unit,
i ? "," : "", ids[i], tests[i].name, tests[i].detail, tests[i].unit,
(unsigned long long)tests[i].start_n, tests[i].work_per_n,
tests[i].ref_rate, tests[i].weight,
display_metric(&tests[i], &multi[i]), multi[i].rate, multi[i].score,
display_metric(&tests[i], &multi[i]), multi[i].rate,
multi[i].seconds, (unsigned long long)multi[i].iters, multi[i].threads,
(unsigned long long)multi[i].checksum,
display_metric(&tests[i], &single[i]), single[i].rate, single[i].score,
display_metric(&tests[i], &single[i]), single[i].rate,
single[i].seconds, (unsigned long long)single[i].iters, single[i].threads,
(unsigned long long)single[i].checksum);
if (n < 0 || (size_t)n >= sizeof(payload) - used) return 0;
@@ -268,16 +269,17 @@ static int upload_results(const struct system_info *info, double score,
return 0;
}
if (status < 200 || status >= 300) { fprintf(stderr, " upload failed: server returned HTTP %d\n", status); return 0; }
if (!json_string_field(response_body, "claim_url", claim_url, sizeof(claim_url))) {
fprintf(stderr, " upload failed: server did not return a claim link\n");
if (!json_string_field(response_body, "result_url", result_url, sizeof(result_url))) {
fprintf(stderr, " upload failed: server did not return a result link\n");
return 0;
}
printf(" Results uploaded (HTTP %d).\n", status);
{
printf(" View your result: %s\n", result_url);
if (json_string_field(response_body, "claim_url", claim_url, sizeof(claim_url))) {
const char *claim_code = strrchr(claim_url, '/');
printf(" Claim code: %s\n", claim_code && claim_code[1] ? claim_code + 1 : claim_url);
printf(" Claim your result: %s\n", claim_url);
}
printf(" Claim your result: %s\n", claim_url);
return 1;
#if !defined(_WIN32)