perf(miner): use CLOCK_MONOTONIC_COARSE and counter-based rate reporting

Replace time() syscall with clock_gettime(CLOCK_MONOTONIC_COARSE) and
gate timestamp/rate checks behind a batch counter to avoid clock overhead
on every iteration. Set reporting interval to 2s.
This commit is contained in:
2026-03-30 10:42:30 +02:00
parent 7d4096749a
commit 8709072574

67
miner.c
View File

@@ -4,11 +4,12 @@
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <stddef.h>
#include "sha256/sha256_backend.h"
#include "utils.h"
static const double RATE_INTERVAL_SEC = 5.0;
static const double RATE_INTERVAL_SEC = 2.0;
static inline uint32_t load_u32_be(const uint8_t *p) {
return ((uint32_t)p[0] << 24) |
@@ -43,11 +44,13 @@ static int compute_hash_batch(
sha256d80_midstate_t mid;
uint32_t i = 0;
sha256d80_midstate_init(&mid, header_76);
/* Backend is now initialized; use direct scan to skip per-call pthread_once */
sha256_backend_ensure_init();
while ((batch_size - i) >= 4U) {
uint32_t n0 = start_nonce + i;
sha256_state_t st1[4];
uint32_t mask = sha256d80_scan_4way(&mid, n0, target_words, st1);
uint32_t mask = sha256d80_scan_4way_direct(&mid, n0, target_words, st1);
if (mask & 1U) {
*found_nonce = n0;
@@ -120,10 +123,14 @@ int mine_block(
uint32_t target_words[8];
uint32_t nonce;
long long attempts = 0;
time_t t_start;
struct timespec ts_start, ts_now;
double last_rate_t;
long long last_rate_n = 0;
double last_tsu;
uint32_t batch_count = 0;
/* Check timestamp update every 32 batches, rate every 32 batches (~1s) */
#define TSU_CHECK_MASK 31U
#define RATE_CHECK_MASK 31U
memset(out, 0, sizeof(*out));
@@ -139,30 +146,34 @@ int mine_block(
nonce = (uint32_t)rand();
}
t_start = time(NULL);
last_rate_t = (double)t_start;
last_tsu = (double)t_start;
clock_gettime(CLOCK_MONOTONIC_COARSE, &ts_start);
last_rate_t = (double)ts_start.tv_sec + (double)ts_start.tv_nsec * 1e-9;
last_tsu = last_rate_t;
while (1) {
uint32_t found_nonce = 0;
uint8_t found_digest[32];
time_t now_t;
double now;
if (atomic_load(stop_flag) != 0) {
return 0;
}
now_t = time(NULL);
now = (double)now_t;
batch_count++;
if (timestamp_update_interval > 0 && (now - last_tsu) >= (double)timestamp_update_interval) {
write_u32_le(header_76 + 68, (uint32_t)now_t);
last_tsu = now;
/* Timestamp update: check every 64 batches to reduce clock calls */
if (timestamp_update_interval > 0 && (batch_count & TSU_CHECK_MASK) == 0) {
clock_gettime(CLOCK_MONOTONIC_COARSE, &ts_now);
double now = (double)ts_now.tv_sec + (double)ts_now.tv_nsec * 1e-9;
if (now - last_tsu >= (double)timestamp_update_interval) {
write_u32_le(header_76 + 68, (uint32_t)ts_now.tv_sec);
last_tsu = now;
}
}
if (compute_hash_batch(header_76, nonce, batch_size, target_words, &found_nonce, found_digest)) {
double total = now - (double)t_start;
clock_gettime(CLOCK_MONOTONIC_COARSE, &ts_now);
double total = ((double)ts_now.tv_sec + (double)ts_now.tv_nsec * 1e-9)
- ((double)ts_start.tv_sec + (double)ts_start.tv_nsec * 1e-9);
if (total <= 0.0) {
total = 1e-6;
}
@@ -181,18 +192,24 @@ int mine_block(
attempts += batch_size;
nonce += batch_size;
now = (double)time(NULL);
if ((now - last_rate_t) >= RATE_INTERVAL_SEC) {
double dt = now - last_rate_t;
if (dt <= 0.0) {
dt = 1e-6;
/* Rate reporting: check every 128 batches */
if ((batch_count & RATE_CHECK_MASK) == 0) {
clock_gettime(CLOCK_MONOTONIC_COARSE, &ts_now);
double now = (double)ts_now.tv_sec + (double)ts_now.tv_nsec * 1e-9;
if (now - last_rate_t >= RATE_INTERVAL_SEC) {
double dt = now - last_rate_t;
if (dt <= 0.0) {
dt = 1e-6;
}
if (status_cb != NULL) {
double hr = (double)(attempts - last_rate_n) / dt;
status_cb(attempts, hr, status_ctx);
}
last_rate_t = now;
last_rate_n = attempts;
}
if (status_cb != NULL) {
double hr = (double)(attempts - last_rate_n) / dt;
status_cb(attempts, hr, status_ctx);
}
last_rate_t = now;
last_rate_n = attempts;
}
}
#undef TSU_CHECK_MASK
#undef RATE_CHECK_MASK
}