Skip to content

Fix #123: Use correct pooled standard deviation formula in multi-worker aggregation#142

Open
mcurrier2 wants to merge 1 commit into
mainfrom
fix/123-pooled-stddev-aggregation
Open

Fix #123: Use correct pooled standard deviation formula in multi-worker aggregation#142
mcurrier2 wants to merge 1 commit into
mainfrom
fix/123-pooled-stddev-aggregation

Conversation

@mcurrier2

Copy link
Copy Markdown
Collaborator

Summary

  • Fix pooled std_dev formula in aggregate_latency_metrics() to use the law of total variance: Var(X) = E[Var(X|G)] + Var(E[X|G]), which accounts for between-group mean differences
  • The old formula sqrt(sum(n_i * sigma_i^2) / N) only computed within-group variance, underestimating combined std_dev when workers have different mean latencies
  • Add two unit tests validating the corrected formula

Test plan

  • New test: test_pooled_stddev_between_group_variance verifies between-group differences are captured
  • New test: test_pooled_stddev_same_means verifies same-mean case still works
  • All existing tests pass
  • Clippy clean, MSRV 1.70 compatible

Fixes #123

Made with Cursor

…er aggregation

The previous implementation computed std_dev as sqrt(sum(n_i * sigma_i^2) / N),
which only accounts for within-group variance. When workers have different mean
latencies, this significantly underestimates the true combined standard deviation.

Apply the law of total variance: Var(X) = E[Var(X|G)] + Var(E[X|G]), which
adds between-group variance (weighted squared deviation of each worker's mean
from the combined mean) to the within-group variance.

- Fix pooled std_dev formula in aggregate_latency_metrics()
- Add test verifying between-group mean differences are captured
- Add test verifying same-mean case still produces correct result
- All existing tests passing, clippy clean

AI-assisted-by: Claude Opus 4.6
Co-authored-by: Cursor <cursoragent@cursor.com>
@coderabbitai

coderabbitai Bot commented Jul 1, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Summary by CodeRabbit

  • Bug Fixes

    • Corrected aggregated latency statistics for multi-worker runs so reported variability now reflects differences between workers more accurately.
    • Improved benchmark startup and process handling to better detect failures and avoid silently continuing after bad exits.
    • Fixed blocking and async benchmark argument handling so spawned runs inherit the expected runtime settings more reliably.
  • Tests

    • Added coverage for pooled latency standard deviation calculations to verify behavior when worker timings differ or match.

Walkthrough

Adds three planning/documentation Markdown files (release-polish-plan.glow, release-polish-plan.md, tier1-pr-diffs.md) recording a release-polish review pass, filed issues, and Tier 1 PR diffs. Separately, corrects the pooled standard deviation formula in metrics.rs multi-worker latency aggregation and adds two unit tests.

Changes

Release Polish Planning Documentation

Layer / File(s) Summary
Release polish plan (glow)
.cursor/plans/release-polish-plan.glow
New document with objective, review groups, categorized inline fixes, filed GitHub issues (#120#131), validation results, and files-modified summary.
Release polish plan (markdown)
.cursor/plans/release-polish-plan.md
New/updated document with metadata, review groups, inline fixes tables, filed issues, validation, files-modified, additional documentation review pass, and Cargo.toml/LICENSE review notes.
Tier 1 PR diff notes
.cursor/plans/tier1-pr-diffs.md
Adds before/after snippets for PRs #137#141 documenting pthread init error checks, wait() status checks, include_first_message handling, and server spawn CLI flag forwarding.

Pooled Standard Deviation Fix

Layer / File(s) Summary
Pooled variance calculation fix
src/metrics.rs
Replaces the weighted-average variance approximation with a law-of-total-variance computation combining within-group and between-group variance for aggregated std_dev_ns.
Unit tests for pooled std_dev_ns
src/metrics.rs
Expands test imports and adds two tests validating pooled std_dev_ns behavior with differing and identical worker means.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Related issues: #123 (Incorrect pooled standard deviation in multi-worker metrics aggregation)

Suggested labels: documentation, bug, metrics

Suggested reviewers: (none identified)

🐰 A pooled variance once ran astray,
ignoring the means that drifted away.
Now within and between are summed just right,
with tests standing guard through the night,
while planning docs chart the release-polish way.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning The PR adds unrelated .cursor/plans/* release-plan documents that are not required to fix issue #123. Split the planning-document edits into a separate PR or remove them if they are not needed for the #123 fix.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely summarizes the main fix to pooled standard deviation in multi-worker aggregation.
Description check ✅ Passed The description matches the template's main sections and provides summary and testing, with only minor checklist gaps.
Linked Issues check ✅ Passed The code change implements pooled variance correctly and adds tests that validate the #123 behavior.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.cursor/plans/release-polish-plan.md:
- Around line 108-115: The release validation summary is inconsistent between
the plan documents, with mismatched test totals and modified-file counts. Update
the Validation summary in the release-polish plan using the same authoritative
numbers as the corresponding release-polish-plan.glow entry, and ensure both
summaries in the release-plan documents reflect identical counts. Keep the fix
localized to the Validation section and the release summary fields so the two
files stay synchronized.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Enterprise

Run ID: 692b7130-f254-4965-b23c-1b0a49e6dac7

📥 Commits

Reviewing files that changed from the base of the PR and between d586320 and 8832f3c.

⛔ Files ignored due to path filters (6)
  • .cursor/plans/benchmark-chore-release-polish.csv is excluded by !**/*.csv
  • .cursor/plans/benchmark-fix-121-blocking-forward-duration.csv is excluded by !**/*.csv
  • .cursor/plans/benchmark-fix-122-blocking-roundtrip-first-message.csv is excluded by !**/*.csv
  • .cursor/plans/benchmark-fix-124-async-server-flag-forwarding.csv is excluded by !**/*.csv
  • .cursor/plans/benchmark-fix-129-server-exit-status-check.csv is excluded by !**/*.csv
  • .cursor/plans/benchmark-fix-131-shm-direct-mutex-init-checks.csv is excluded by !**/*.csv
📒 Files selected for processing (4)
  • .cursor/plans/release-polish-plan.glow
  • .cursor/plans/release-polish-plan.md
  • .cursor/plans/tier1-pr-diffs.md
  • src/metrics.rs

Comment on lines +108 to +115
## Validation

```
cargo fmt ✓ (no changes)
cargo clippy ✓ (0 warnings with -D warnings)
cargo test ✓ (42 passed, 0 failed)
cargo build ✓
```

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '--- files ---\n'
git ls-files '.cursor/plans/release-polish-plan.md' '.cursor/plans/release-polish-plan.glow' || true

printf '\n--- md lines 100-150 ---\n'
sed -n '100,150p' .cursor/plans/release-polish-plan.md | cat -n

printf '\n--- glow lines 100-150 ---\n'
sed -n '100,150p' .cursor/plans/release-polish-plan.glow | cat -n

Repository: redhat-performance/rusty-comms

Length of output: 259


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '--- file stats ---\n'
wc -l .cursor/plans/release-polish-plan.md .cursor/plans/release-polish-plan.glow

printf '\n--- md validation/search ---\n'
rg -n "cargo (fmt|clippy|test|build)|passed|modified|files" .cursor/plans/release-polish-plan.md

printf '\n--- glow validation/search ---\n'
rg -n "cargo (fmt|clippy|test|build)|passed|modified|files" .cursor/plans/release-polish-plan.glow

Repository: redhat-performance/rusty-comms

Length of output: 259


🏁 Script executed:

#!/bin/bash
set -euo pipefail

python3 - <<'PY'
from pathlib import Path
for p in [Path('.cursor/plans/release-polish-plan.md'), Path('.cursor/plans/release-polish-plan.glow')]:
    print(f'--- {p} ---')
    text = p.read_text()
    for needle in ['42 passed', '472 passed', '17', '16', 'cargo fmt', 'cargo clippy', 'cargo test', 'cargo build']:
        if needle in text:
            print('contains', needle)
PY

Repository: redhat-performance/rusty-comms

Length of output: 499


🏁 Script executed:

#!/bin/bash
set -euo pipefail

python3 - <<'PY'
from pathlib import Path
for p in [Path('.cursor/plans/release-polish-plan.md'), Path('.cursor/plans/release-polish-plan.glow')]:
    print(f'FILE: {p}')
    try:
        text = p.read_text()
    except Exception as e:
        print('ERROR:', e)
        continue
    for i, line in enumerate(text.splitlines(), 1):
        if 100 <= i <= 150:
            print(f'{i:4d}: {line}')
PY

Repository: redhat-performance/rusty-comms

Length of output: 9171


Reconcile the release summary across .cursor/plans/release-polish-plan.md and .cursor/plans/release-polish-plan.glow. The validation totals and modified-file counts diverge (42 passed vs 472 passed, 17 vs 16 files), so one authoritative summary needs to be synced in both places.

🧰 Tools
🪛 markdownlint-cli2 (0.22.1)

[warning] 110-110: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.cursor/plans/release-polish-plan.md around lines 108 - 115, The release
validation summary is inconsistent between the plan documents, with mismatched
test totals and modified-file counts. Update the Validation summary in the
release-polish plan using the same authoritative numbers as the corresponding
release-polish-plan.glow entry, and ensure both summaries in the release-plan
documents reflect identical counts. Keep the fix localized to the Validation
section and the release summary fields so the two files stay synchronized.

@github-actions

github-actions Bot commented Jul 1, 2026

Copy link
Copy Markdown

📈 Changed lines coverage: 100.00% (9/9)

✅ All new and modified lines are covered by tests!

📊 Code Coverage Summary

File Line Coverage Uncovered Lines
src/benchmark.rs 84.13%
(509/605)
75, 78, 89, 93, 102, 105, 107, 124, 424, 429-434, 441-446, 513-516, 621, 705, 717-719, 739, 808-810, 815, 836, 841, 859, 965, 969-972, 974, 983-986, 988, 1064, 1095, 1098, 1100-1101, 1110-1111, 1253, 1266, 1283, 1406, 1415, 1417-1418, 1421-1422, 1428-1429, 1434-1435, 1437, 1442-1443, 1447-1449, 1454-1455, 1458-1459, 1491, 1549-1553, 1555-1561, 1563, 1566, 1723, 1738
src/benchmark_blocking.rs 74.32%
(327/440)
97, 111, 127, 263, 369, 380-382, 402, 434, 495, 594, 607, 621, 651-654, 739-742, 761, 765, 780, 822, 824-826, 830, 833-835, 837, 840, 842-846, 848-849, 857-861, 863-867, 870-871, 875-876, 911, 960, 1042, 1053, 1083, 1086, 1151-1156, 1158, 1216-1219, 1224, 1237, 1240-1243, 1247, 1249-1252, 1254, 1256-1257, 1259-1260, 1263, 1265-1270, 1272, 1276-1277, 1279, 1281, 1305, 1317-1322, 1324, 1344-1347
src/cli.rs 92.39%
(85/92)
691, 790, 830, 832, 853-855
src/execution_mode.rs 100.00%
(14/14)
``
src/ipc/mod.rs 63.64%
(49/77)
134, 458, 460-463, 773-774, 789-790, 808-809, 840, 843, 846, 851, 878-879, 893, 895, 915, 917, 1040-1042, 1231-1233
src/ipc/posix_message_queue.rs 46.09%
(59/128)
139-140, 213-215, 217, 224, 229, 332-335, 337, 345, 437, 441-442, 446, 449-452, 454-458, 539, 679, 782, 789-790, 807-808, 819-820, 831-832, 849-850, 906, 910-911, 914-919, 921-923, 927, 929-931, 933, 935-937, 941-943, 945-947, 994-995, 1017
src/ipc/posix_message_queue_blocking.rs 72.16%
(127/176)
172, 182, 221, 251-255, 274, 325, 368, 387-390, 416-418, 422-423, 425-426, 436, 455, 457-458, 460-461, 474-475, 477-478, 484, 486-491, 493-495, 497-498, 503, 505-506, 508-509
src/ipc/shared_memory.rs 69.36%
(163/235)
69, 152, 156, 257-258, 268-269, 273, 401-402, 428-430, 432, 450-452, 454-455, 457-461, 478, 485, 491, 494-495, 499, 503, 507-508, 513-514, 677-678, 681-682, 685, 687, 692-693, 720-721, 724-725, 732-734, 736, 738-743, 745-746, 749-750, 752-756, 763, 793, 795-796, 798, 802
src/ipc/shared_memory_blocking.rs 77.35%
(222/287)
199-201, 203-204, 207-209, 212-213, 215, 220, 222, 226-228, 233, 241-243, 246-248, 251-252, 254, 257, 260-261, 264-265, 269-270, 272, 276-277, 279, 315-316, 403-404, 428-432, 544, 552, 602, 619, 706, 772, 805-806, 808-809, 816, 833, 835-836, 838, 871, 880, 890, 912
src/ipc/shared_memory_direct.rs 83.25%
(159/191)
400-403, 472-479, 483, 511, 536-539, 543-544, 590-591, 603, 633, 640-641, 697-698, 704, 726, 731-732
src/ipc/tcp_socket.rs 59.43%
(63/106)
31-32, 61, 96, 113-114, 118, 124-125, 129, 136-137, 141, 147-148, 152, 171-172, 175-177, 184-185, 188, 362-363, 366-367, 370-371, 376-377, 422, 429, 447-449, 478, 480-482, 484, 487
src/ipc/tcp_socket_blocking.rs 94.23%
(98/104)
145, 170, 322-325
src/ipc/unix_domain_socket.rs 59.43%
(63/106)
29-30, 58, 93, 103, 122-123, 127, 133-134, 138, 145-146, 150, 156-157, 161, 180-181, 184-186, 193-194, 197, 346-347, 350-351, 354-355, 360-361, 412-414, 443, 445-447, 449, 452, 468
src/ipc/unix_domain_socket_blocking.rs 92.06%
(116/126)
287-288, 294-296, 298, 363-366
src/logging.rs 100.00%
(13/13)
``
src/main.rs 45.76%
(162/354)
85-87, 89, 130-131, 141-145, 149-151, 153-154, 156-157, 177-180, 204-208, 216, 222, 225, 230-233, 238-239, 245, 251, 253-255, 257, 263-264, 270, 275, 278-279, 283, 285-286, 290-291, 293, 299, 303-304, 306-311, 313-314, 317, 326, 329-330, 333, 380-383, 390, 392-396, 399-402, 404-405, 407-408, 410, 412-418, 422, 424-427, 430, 434-436, 440, 442, 445, 449, 454-457, 463-464, 470-471, 477, 479-480, 484, 486, 491-493, 497, 500-501, 503-504, 509, 511-513, 517-518, 520, 527, 532-533, 535-540, 542-543, 547, 556, 559-560, 563, 565, 584, 591, 595-597, 599, 627-628, 636, 669, 704, 729, 733, 736-739, 795-796, 803-804, 807, 834-835, 838, 875, 896-897, 901-904, 926, 953, 962, 967, 972-973
src/metrics.rs 84.38%
(162/192)
455-460, 493-494, 552, 558, 579-582, 732-734, 736, 768, 833, 838, 881, 904, 962, 990, 994, 1015, 1017-1018, 1023
src/results.rs 56.60%
(253/447)
726, 735-737, 739-740, 743-744, 747, 769, 772-773, 776, 778, 781, 785-790, 800-801, 804-809, 826, 838-839, 841, 843, 846-847, 849, 853, 880, 904-906, 909-910, 914-916, 919, 945, 950, 955, 961, 980, 982-983, 985, 987-991, 993, 995-996, 1030, 1071-1072, 1075, 1081-1082, 1086, 1090-1092, 1094-1095, 1119-1123, 1126-1129, 1132-1141, 1151-1152, 1171-1172, 1174-1178, 1180, 1197-1198, 1200-1205, 1207, 1225, 1227-1232, 1250, 1253, 1269-1270, 1285-1287, 1289-1291, 1293-1294, 1296-1297, 1299-1300, 1302, 1304-1305, 1307-1310, 1312-1314, 1316-1318, 1321, 1325-1326, 1334-1339, 1341-1342, 1346-1347, 1351-1353, 1355, 1359-1360, 1369-1372, 1376-1378, 1382, 1384-1385, 1393-1394, 1399, 1406-1410, 1412, 1610-1611, 1831-1832, 1834-1835
src/results_blocking.rs 95.51%
(298/312)
489-490, 492-493, 544, 769, 774, 779, 815, 818-819, 827-828, 886
src/standalone_client.rs 84.57%
(636/752)
40, 68-69, 79, 84-85, 87, 96-99, 109-111, 113, 117, 133, 154, 256, 276, 320, 361, 365, 396, 414, 513, 531, 542, 549, 614, 617-618, 626-646, 648-649, 651, 675, 682, 698, 736, 739, 761-763, 768-769, 857, 877, 893, 921, 924-925, 962, 966, 997, 1001, 1015, 1022, 1105, 1123, 1134, 1141, 1144, 1201, 1204-1205, 1213-1233, 1235-1236, 1238, 1262, 1269, 1272, 1284, 1321, 1324
src/standalone_server.rs 77.97%
(400/513)
138, 161, 187, 204-205, 207, 217-219, 221, 260, 285-286, 309-311, 335-336, 421-422, 425-426, 446-447, 457-458, 461, 463, 465, 475-478, 485, 493-496, 521, 553-554, 569-570, 580-581, 584, 586, 588, 598-601, 608, 619-622, 668, 747-748, 766-768, 772-774, 824-826, 830-831, 834-835, 851-852, 859-862, 871, 876-877, 880, 882, 884, 894, 901-904, 926, 956-958, 962-963, 975-976, 983-986, 995, 1000-1001, 1004, 1006, 1008, 1018, 1027-1030
src/utils.rs 75.00%
(42/56)
143, 147-148, 153, 159, 198-202, 239-242
Total 75.48%
(4020/5326)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Incorrect pooled standard deviation in multi-worker metrics aggregation

1 participant