diff --git a/src/redis-benchmark.c b/src/redis-benchmark.c index 8c9e062980..dfe692c346 100644 --- a/src/redis-benchmark.c +++ b/src/redis-benchmark.c @@ -828,8 +828,21 @@ static void createMissingClients(client c) { } static void showLatencyReport(void) { + if (config.latency_histogram->total_count == 0) { + if (config.csv) { + printf("\"%s\",\"0.00\",\"0.000\",\"0.000\",\"0.000\",\"0.000\",\"0.000\",\"0.000\"\n", config.title); + } else if (config.quiet) { + printf("%*s\r", config.last_printed_bytes, " "); // ensure there is a clean line + printf("%s: 0.00 requests per second, p50=0.000 msec\n", config.title); + } else { + printf("%*s\r", config.last_printed_bytes, " "); // ensure there is a clean line + printf("====== %s ======\n", config.title); + printf("No latency samples collected\n"); + } + return; + } - const float reqpersec = (float)config.requests_finished/((float)config.totlatency/1000.0f); + const float reqpersec = config.totlatency > 0 ? (float)config.requests_finished/((float)config.totlatency/1000.0f) : 0.0f; const float p0 = ((float) hdr_min(config.latency_histogram))/1000.0f; const float p50 = hdr_value_at_percentile(config.latency_histogram, 50.0 )/1000.0f; const float p95 = hdr_value_at_percentile(config.latency_histogram, 95.0 )/1000.0f; @@ -1666,13 +1679,15 @@ int showThroughput(struct aeEventLoop *eventLoop, long long id, void *clientData return SHOW_THROUGHPUT_INTERVAL; } const float dt = (float)(current_tick-config.start)/1000.0; - const float rps = (float)requests_finished/dt; + const float rps = dt > 0 ? (float)requests_finished/dt : 0.0f; const float instantaneous_dt = (float)(current_tick-config.previous_tick)/1000.0; - const float instantaneous_rps = (float)(requests_finished-previous_requests_finished)/instantaneous_dt; + const float instantaneous_rps = instantaneous_dt > 0 ? (float)(requests_finished-previous_requests_finished)/instantaneous_dt : 0.0f; config.previous_tick = current_tick; atomicSet(config.previous_requests_finished,requests_finished); printf("%*s\r", config.last_printed_bytes, " "); /* ensure there is a clean line */ - int printed_bytes = printf("%s: rps=%.1f (overall: %.1f) avg_msec=%.3f (overall: %.3f)\r", config.title, instantaneous_rps, rps, hdr_mean(config.current_sec_latency_histogram)/1000.0f, hdr_mean(config.latency_histogram)/1000.0f); + double avg_mean = config.current_sec_latency_histogram->total_count > 0 ? hdr_mean(config.current_sec_latency_histogram)/1000.0f : 0.0; + double overall_mean = config.latency_histogram->total_count > 0 ? hdr_mean(config.latency_histogram)/1000.0f : 0.0; + int printed_bytes = printf("%s: rps=%.1f (overall: %.1f) avg_msec=%.3f (overall: %.3f)\r", config.title, instantaneous_rps, rps, avg_mean, overall_mean); config.last_printed_bytes = printed_bytes; hdr_reset(config.current_sec_latency_histogram); fflush(stdout); diff --git a/src/redis-cli.c b/src/redis-cli.c index 5dd843a9cf..72093bbf07 100644 --- a/src/redis-cli.c +++ b/src/redis-cli.c @@ -10492,6 +10492,11 @@ static int displayKeyStatsSizeDist(struct hdr_histogram *keysize_histogram) { struct hdr_iter iter; int64_t last_displayed_cumulative_count = 0; + if (keysize_histogram->total_count == 0) { + line_count += cleanPrintfln("No key size samples collected"); + return line_count; + } + hdr_iter_percentile_init(&iter, keysize_histogram, 1); line_count += cleanPrintfln("Key size Percentile Total keys"); diff --git a/tests/integration/redis-benchmark.tcl b/tests/integration/redis-benchmark.tcl index c3254408c8..972054ce08 100644 --- a/tests/integration/redis-benchmark.tcl +++ b/tests/integration/redis-benchmark.tcl @@ -134,6 +134,15 @@ tags {"benchmark network external:skip logreqres:skip"} { r get key } {arg} + test {benchmark: no NaN or Inf in latency report with fast requests} { + # With -n 1 on localhost, totlatency can round to 0 ms. Verify showLatencyReport() handles this gracefully. + set cmd [redisbenchmark $master_host $master_port "-c 1 -n 1 -t set"] + set output [exec {*}$cmd 2>@1] + if {[regexp -nocase {nan|(?:^|[^a-z])inf(?:[^o]|$)} $output]} { + fail "redis-benchmark output contains NaN or Inf: $output" + } + } + # tls specific tests if {$::tls} { test {benchmark: specific tls-ciphers} { diff --git a/tests/integration/redis-cli.tcl b/tests/integration/redis-cli.tcl index 399022b777..98477468e9 100644 --- a/tests/integration/redis-cli.tcl +++ b/tests/integration/redis-cli.tcl @@ -849,4 +849,18 @@ start_server {tags {"cli external:skip"}} { } } +start_server {tags {"cli external:skip"}} { + test "keystats on empty database should not produce garbage stats" { + # On an empty DB the keystats histogram has total_count = 0. Verify hdr_mean(), hdr_stddev(), + # and the percentile calculation handle this gracefully. + set cmd [rediscli [srv host] [srv port] [list --keystats]] + catch {exec {*}$cmd 2>@1} result + assert_match "*Scanning the entire keyspace*" $result + + # The "Note:" line with Mean/StdDeviation is only printed when displayKeyStatsSizeDist() + # compute stats. When keysize_histogram->total_count == 0, it should be skipped entirely. + assert_match "*No key size samples collected*" $result + } +} + file delete ./.rediscli_history_test