Measure authoring efficiency once the node is synced #1
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Once
substrate_sub_libp2p_is_major_syncingreads 0, run the experiments below to find out whether connectivity tuning does anything measurable. Nothing here is worth attempting while syncing — the node does not author until it is caught up.The question
In PoW, peer count does not change our share of hashrate, so it cannot increase how often we find a block. What it can change is waste, in two ways:
Both are waste reduction bounded by current propagation delay. Expect a few percent, not a multiplier. The purpose of these experiments is to find out whether it is even that much.
Blocker: the thing worth measuring is not currently observable
quantus-nodeexports no difficulty metric and no authored-block counter.substrate_proposer_block_constructedcounts proposals constructed, not rounds won.quantus-minerexports no solutions-found counter — the full set isminer_hashes_total,miner_hash_rate,miner_cpu_hash_rate,miner_gpu_hash_rate,miner_active_jobs,miner_workers,miner_cpu_workers,miner_gpu_devices,miner_effective_cpus, and nothing else.So "do we win the share of blocks our hashrate predicts?" — the only honest measure of orphan and stale-work loss — cannot be plotted today.
Options to close the gap, cheapest first:
qzp2AxZw…), via RPC against the local node. Needs a small exporter or a timer writing to a textfile collector. No upstream change required.doc/wormhole-rewards.md§8.Do the chain-query exporter first. Without it the experiments below can only measure proxies, and proxies will not settle the question.
Baseline to capture before changing anything
Let it run at least 24h synced, then record:
miner_hash_rate(measured 183 MH/s on the 4090 at ~450 W)substrate_sub_libp2p_peers_count, plus the in/out split fromsubstrate_sub_libp2p_connections_opened_total{direction=}rate(substrate_proposer_block_constructed_count[5m]) * 60) — should sit near 10/min at a 6 s targetExperiments
1. Peer count
Current defaults are
--out-peers 8,--in-peers 32. Inbound dominates by an order of magnitude — measured 63 inbound connection opens against 5 outbound, with 23 established inbound. So--in-peersis the binding constraint and--out-peersis nearly irrelevant here; raising the latter will do close to nothing.Try
--in-peers 64. Hold for 24h. Compare authored-share and rounds/min against baseline.Cost side worth watching: this chain uses Dilithium for p2p identity (
Using litep2p network backend (with Dilithium)), so post-quantum handshakes make each peer more expensive than on a typical Substrate chain. Watch node CPU and bandwidth, not just the peer gauge.One genuine advantage here: mining is external, so the node's CPU is not competing with hashing. This node can afford more peers than the usual solo-miner advice assumes.
2. GPU power limit
Measured on a 5090: 600 W → 368 MH/s (0.60 MH/s/W), 450 W → 305 (0.68), 400 W floor → 281 (0.70). 18% better hash per watt at the floor for 78% of peak. The 4090 measured 183 MH/s at ~450 W (0.41 MH/s/W); its own curve is unmeasured.
If the goal is paying an electricity bill rather than maximising hashrate, the floor is likely the right operating point. Measure the 4090's curve, then decide.
3. Miner placement
The GPU host also serves helexa inference from the same card. Mining saturates it. Quantify what inference actually loses before deciding whether to move mining, throttle it, or accept the contention — this is the open decision recorded in
readme.md.Definition of done
A number, not an impression: authored blocks as a fraction of the share our hashrate predicts, before and after each change, with enough samples to be more than noise. At ~10 blocks/min network-wide and a small hashrate share, that may need days rather than hours — decide the sample size up front rather than stopping when the graph looks favourable.
Context
asset/grafana/andasset/prometheus/; edit there and redeploy, not in the Grafana UI (allowUiUpdates: false).Correction: experiment 1 had the wrong knob
The original recommendation — raise
--in-peersto 64, leave--out-peersalone — was backwards. Do not run it as written.What I measured wrong
I used cumulative connection opens: 63 inbound against 5 outbound, concluded inbound dominated, and inferred
--in-peerswas the binding cap.Cumulative opens measure churn, not occupancy. Inbound connections arrive and leave constantly; outbound ones are deliberately maintained and stable. So a high inbound open count says nothing about whether the inbound cap is full.
The right measurement
opened − closedper direction, against the cap. Now that the node is synced and dialable:Also:
substrate_sub_libp2p_peerset_num_discovered= 300.--in-peerswould change nothing — inbound is demand-driven, bounded by how many peers choose to dial us, not by our ceiling.Corrected experiment 1
Change
--out-peersfrom 8 to 24. Leave--in-peersat its default.Rationale: with 300 discovered peers and 8 dial slots, more outbound links mean learning about new tips from more independent sources, which is the mechanism that shrinks the stale-tip window. Keep it modest — this chain uses Dilithium for p2p identity, so each peer costs more than on a typical Substrate chain. 8 → 24 is defensible; 8 → 100 is not.
The gain remains bounded: this reduces wasted work, it cannot increase hashrate share. Expect a few percent, and expect it to be hard to distinguish from noise.
Run order
Do not change anything yet. Take a clean 24h baseline first — a stable node with no config changes, since every change restarts it and drops every peer. The exporter now measures what is needed:
quantus_share_observedsum(miner_hash_rate) / quantus_network_hashraterate(substrate_proposer_block_constructed_count[5m]) * 60opened − closedper direction, as abovequantus_difficulty,quantus_block_interval_secondsThen: change
--out-peers, hold 24h, compare the same five.Sample size still governs the answer. At ~10s blocks and ~16% share, 24h is roughly 8600 network blocks and ~1400 of ours — enough that a few-percent effect is near the noise floor. Decide before looking whether a difference that small would change anything you do; if not, the honest outcome is "no measurable effect", and that is a result worth recording rather than a failure.
Baseline window opens: 2026-09-01T03:46Z
Earliest the
--out-peerschange should be applied: 2026-09-02T03:46Z.GPU power limits were reduced immediately before this, so every earlier hashrate figure in this issue is stale. The baseline must run against the new limits or the expected-share denominator is wrong.
Configuration under test (baseline arm)
Ours: 216.8 MH/s.
--out-peersand--in-peersat their defaults of 8 and 32.Chain state at window open
Observed and expected within 0.06pp of each other at window open. That is a coincidence of timing rather than a result — the window is what produces a result.
Note outbound held is 4 of 8, not saturated at this instant, where it was 9 of 8 earlier. Occupancy fluctuates as peers rotate; the case for raising the cap rests on it sitting at the cap over hours, which is what this window will show. If outbound averages well under 8 across 24h, the whole experiment is moot and that is a valid outcome to record.
What must not happen during the window
Do not push. Ten commits are outstanding, several touching the node unit or its config, so a deploy restarts the node and drops every peer — which resets peer occupancy and voids the arm.
If those commits should land sooner, the honest sequence is: push, wait ~30 minutes for peers to re-establish, then reopen the window with a new timestamp. Losing a few hours of baseline is cheaper than comparing across a restart.
Nothing else in flight touches the node: GPU power limits are applied by
nvidia-smiwithout restarting the miner, and the arena exporter reads over RPC.At 2026-09-02T03:46Z
--out-peers 24in the node matrix, deploy, wait ~30 min.Sample size caveat stands: ~8,000 network blocks and ~1,250 of ours per arm, so a few-percent effect sits near the noise floor. The decision of whether a 1–2% difference would change anything should be made now, before the numbers exist.
Correction to the previous comment: the push warning was overstated
I said "ten commits are outstanding, several touching the node unit or its config". That was wrong — I was quoting a stale count from my own commit log rather than checking
origin/main.Actual state at the time of writing: one unpushed commit,
e178bcb(boot-time GPU power limits).It touches only
asset/gpu/*,asset/systemd/nvidia-*,script/infra-setup.shandreadme.md. Nothing under the node's unit, binary or config, and its effects are already applied to the hosts by hand.So pushing it during the baseline window is safe. The deploy triggers (
asset/**matches thepaths:filter) but is content-addressed —push()compares by checksum, nothing the node depends on has changed,RESTARTstays 0, andsystemctl restart quantus-nodeis not called. Peer occupancy is undisturbed.The general rule still holds and is worth keeping: a push that changes the node's unit, binary or rendered config restarts it and voids the arm. Check what a pending commit actually touches before assuming either way — the deploy log's
changed:lines say exactly what moved.