@blinklabs/dingo 0.27.1 → 0.27.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/RELEASE_NOTES.md +34 -0
- package/benchmark_results_bp_pi.md +50 -0
- package/benchmark_results_targeted.md +73 -38
- package/generate_benchmarks.sh +1 -0
- package/generate_bp_pi_report.sh +309 -0
- package/package.json +1 -1
package/RELEASE_NOTES.md
CHANGED
|
@@ -1,6 +1,40 @@
|
|
|
1
1
|
# Release Notes
|
|
2
2
|
|
|
3
3
|
|
|
4
|
+
## v0.27.1 (March 16, 2026)
|
|
5
|
+
|
|
6
|
+
**Title:** Smoother reconnects and safer chain-sync
|
|
7
|
+
|
|
8
|
+
**Date:** March 16, 2026
|
|
9
|
+
|
|
10
|
+
**Version:** v0.27.1
|
|
11
|
+
|
|
12
|
+
Hi folks! Here’s what we shipped in v0.27.1.
|
|
13
|
+
|
|
14
|
+
### ✨ What's New
|
|
15
|
+
|
|
16
|
+
- **Better chain-sync intersection:** Resuming sync is easier and faster because chain-sync uses a denser, wider set of intersect points to improve `ChainSync` intersection behavior.
|
|
17
|
+
|
|
18
|
+
### 💪 Improvements
|
|
19
|
+
|
|
20
|
+
- **Inbound connection reuse and `TxSubmission`:** Networking is more rock-solid on reconnect because peer reuse and governance now normalize exact peer addresses, require client-capable connections for reuse, and start `TxSubmission` on duplex inbound connections.
|
|
21
|
+
- **Stake snapshot and epoch summary upserts:** Data storage is more consistent across supported databases because write paths now upsert across DB backends and report errors more clearly.
|
|
22
|
+
- **More robust delegation parsing:** Delegation reads are more reliable because parsing now handles multiple account encodings with expanded tests.
|
|
23
|
+
|
|
24
|
+
### 🔧 Fixes
|
|
25
|
+
|
|
26
|
+
- **Dependency refresh:** Upgrades are less error-prone because Go modules were refreshed (including AWS SDK v2/S3, `golang.org/x/*`, `plutigo` v0.0.27, `go-ethereum` v1.17.1, and `google.golang.org/api` v0.271.0).
|
|
27
|
+
|
|
28
|
+
### 📋 What You Need to Know
|
|
29
|
+
|
|
30
|
+
- **Go module sync (some builds):** You’re all set for most setups, but if you vendor dependencies or run reproducible builds you may need to re-sync Go modules (update `go.mod`/`go.sum`) to pick up refreshed versions.
|
|
31
|
+
|
|
32
|
+
### 🙏 Thank You
|
|
33
|
+
|
|
34
|
+
Thank you for trying!
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
4
38
|
## v0.27.0 (March 15, 2026)
|
|
5
39
|
|
|
6
40
|
**Title:** S3-backed CI tests and embedded network configs
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# Four-Thread Block Producer Sizing Report (Non-Pi Host)
|
|
2
|
+
|
|
3
|
+
Assumptions:
|
|
4
|
+
- `storageMode=core`
|
|
5
|
+
- `runMode=serve`, `blob=badger`, `metadata=sqlite`
|
|
6
|
+
- `GOMAXPROCS=4`
|
|
7
|
+
- immutable fixture: `database/immutable/testdata`
|
|
8
|
+
- measurements were collected on non-Pi hardware and are a sizing proxy, not Raspberry Pi device benchmarks
|
|
9
|
+
- block producer peer count remains small; this is not a relay profile
|
|
10
|
+
|
|
11
|
+
## Load Footprint
|
|
12
|
+
|
|
13
|
+
| Profile | Elapsed | Peak RSS | Notes |
|
|
14
|
+
| --- | --- | --- | --- |
|
|
15
|
+
| `core-default` | `100.35s` | `568.1 MB` | Current default `serve/core` cache profile |
|
|
16
|
+
|
|
17
|
+
## Recommendation
|
|
18
|
+
|
|
19
|
+
For Raspberry Pi-class sizing in `storageMode=core`, the current default `serve/core` profile is already in the measured low-memory range on this four-thread non-Pi host.
|
|
20
|
+
Explicit Badger cache settings still override these defaults if an operator wants to tune further.
|
|
21
|
+
Treat this as a sizing baseline rather than a direct Raspberry Pi hardware measurement.
|
|
22
|
+
|
|
23
|
+
# Four-Thread Block Producer Sizing Benchmark Results (Non-Pi Host)
|
|
24
|
+
|
|
25
|
+
## Latest Results
|
|
26
|
+
|
|
27
|
+
### Test Environment
|
|
28
|
+
- **Date**: March 15, 2026
|
|
29
|
+
- **Go Version**: 1.25.8
|
|
30
|
+
- **OS**: Linux
|
|
31
|
+
- **Architecture**: aarch64
|
|
32
|
+
- **CPU Cores**: 128
|
|
33
|
+
- **Data Source**: database/immutable/testdata plus local immutable load runs
|
|
34
|
+
- **Scope**: Four-thread block producer path (GOMAXPROCS=4) in core mode on a non-Pi host
|
|
35
|
+
|
|
36
|
+
### Benchmark Results
|
|
37
|
+
|
|
38
|
+
All benchmarks run with `-benchmem` flag. Iterations are Go benchmark iteration counts; benchmark-specific throughput metrics (for example `blocks/sec`) are reported separately.
|
|
39
|
+
|
|
40
|
+
| Benchmark | Iterations | Time/op | Extra Metrics | Memory/op | Allocs/op |
|
|
41
|
+
|-----------|------------|---------|---------------|-----------|-----------|
|
|
42
|
+
| ledger:Blockfetch Near Tip Queued Header Predecoded | 155935 | 36391ns | 27479 blocks/sec | 2KB | 51 |
|
|
43
|
+
| ledger:Blockfetch Near Tip Throughput | 181371 | 66974ns | 14931 blocks/sec | 25KB | 128 |
|
|
44
|
+
| ledger:Blockfetch Near Tip Throughput Predecoded | 328588 | 36882ns | 27113 blocks/sec | 2KB | 50 |
|
|
45
|
+
| ledger:Verify Block Header/direct | 5946 | 1005264ns | - | 2KB | 29 |
|
|
46
|
+
| ledger:Verify Block Header/ledger_state | 6008 | 997998ns | - | 2KB | 29 |
|
|
47
|
+
|
|
48
|
+
## Performance Changes
|
|
49
|
+
|
|
50
|
+
No previous results found. This is the first benchmark run.
|
|
@@ -3,13 +3,13 @@
|
|
|
3
3
|
## Latest Results
|
|
4
4
|
|
|
5
5
|
### Test Environment
|
|
6
|
-
- **Date**: March
|
|
6
|
+
- **Date**: March 15, 2026
|
|
7
7
|
- **Go Version**: 1.25.8
|
|
8
8
|
- **OS**: Linux
|
|
9
9
|
- **Architecture**: aarch64
|
|
10
10
|
- **CPU Cores**: 128
|
|
11
|
-
- **Data Source**: database/immutable/testdata
|
|
12
|
-
- **Scope**: BP runtime
|
|
11
|
+
- **Data Source**: database/immutable/testdata plus synthetic relay fanout/control-loop benchmarks
|
|
12
|
+
- **Scope**: BP and relay runtime paths
|
|
13
13
|
|
|
14
14
|
### Benchmark Results
|
|
15
15
|
|
|
@@ -17,51 +17,86 @@ All benchmarks run with `-benchmem` flag. Iterations are Go benchmark iteration
|
|
|
17
17
|
|
|
18
18
|
| Benchmark | Iterations | Time/op | Extra Metrics | Memory/op | Allocs/op |
|
|
19
19
|
|-----------|------------|---------|---------------|-----------|-----------|
|
|
20
|
-
|
|
|
21
|
-
|
|
|
22
|
-
|
|
|
23
|
-
|
|
|
24
|
-
|
|
|
25
|
-
|
|
|
26
|
-
|
|
|
27
|
-
|
|
|
28
|
-
|
|
|
29
|
-
|
|
|
20
|
+
| connmanager:Has Inbound From Host/10 | 81306320 | 62.31ns | - | 0B | 0 |
|
|
21
|
+
| connmanager:Has Inbound From Host/100 | 94509072 | 70.91ns | - | 0B | 0 |
|
|
22
|
+
| connmanager:Has Inbound From Host/1000 | 92533866 | 64.39ns | - | 0B | 0 |
|
|
23
|
+
| connmanager:Has Inbound From Host/500 | 99476421 | 59.57ns | - | 0B | 0 |
|
|
24
|
+
| connmanager:Try Reserve Inbound Slot Parallel/10 | 15721854 | 388.8ns | - | 0B | 0 |
|
|
25
|
+
| connmanager:Try Reserve Inbound Slot Parallel/100 | 7024470 | 823.6ns | - | 0B | 0 |
|
|
26
|
+
| connmanager:Try Reserve Inbound Slot Parallel/500 | 7173524 | 840.6ns | - | 0B | 0 |
|
|
27
|
+
| connmanager:Update Connection Metrics/10 | 199656918 | 29.24ns | - | 0B | 0 |
|
|
28
|
+
| connmanager:Update Connection Metrics/100 | 203453912 | 29.82ns | - | 0B | 0 |
|
|
29
|
+
| connmanager:Update Connection Metrics/1000 | 203063875 | 30.09ns | - | 0B | 0 |
|
|
30
|
+
| connmanager:Update Connection Metrics/500 | 204545601 | 29.69ns | - | 0B | 0 |
|
|
31
|
+
| event:Publish Subscribers/1 | 7974799 | 650.6ns | - | 0B | 0 |
|
|
32
|
+
| event:Publish Subscribers/10 | 746738 | 7520ns | - | 0B | 0 |
|
|
33
|
+
| event:Publish Subscribers/100 | 61120 | 94657ns | - | 0B | 0 |
|
|
34
|
+
| event:Publish Subscribers/500 | 12976 | 489401ns | - | 0B | 0 |
|
|
35
|
+
| ledger:Block Processing Throughput | 54142 | 95123ns | 10513 blocks/sec | 25KB | 133 |
|
|
36
|
+
| ledger:Block Processing Throughput Predecoded | 144867 | 40441ns | 24728 blocks/sec | 2KB | 51 |
|
|
37
|
+
| ledger:Blockfetch Near Tip Throughput | 172838 | 69818ns | 14323 blocks/sec | 25KB | 129 |
|
|
38
|
+
| ledger:Blockfetch Near Tip Flush Only Predecoded | 342222 | 37234ns | 26857 blocks/sec | 2KB | 50 |
|
|
39
|
+
| ledger:Blockfetch Near Tip Throughput Predecoded | 340428 | 36428ns | 27452 blocks/sec | 2KB | 50 |
|
|
40
|
+
| ledger:Blockfetch Verified Header Dispatch | 156298824 | 38.37ns | - | 0B | 0 |
|
|
41
|
+
| ledger:Verify Block Header/direct | 5907 | 1008310ns | - | 2KB | 29 |
|
|
42
|
+
| ledger:Verify Block Header/ledger_state | 5935 | 1006660ns | - | 2KB | 29 |
|
|
43
|
+
| peergov:Reconcile/100 | 64309 | 93859ns | - | 19KB | 124 |
|
|
44
|
+
| peergov:Reconcile/1000 | 3626 | 1632793ns | - | 250KB | 1597 |
|
|
45
|
+
| peergov:Reconcile/500 | 7881 | 733098ns | - | 124KB | 697 |
|
|
46
|
+
|
|
30
47
|
## Performance Changes
|
|
31
48
|
|
|
32
|
-
Changes
|
|
49
|
+
Changes relative to the earlier **March 15, 2026** baseline below:
|
|
33
50
|
|
|
34
51
|
### Summary
|
|
35
|
-
-
|
|
36
|
-
-
|
|
37
|
-
-
|
|
38
|
-
-
|
|
52
|
+
- Focused timed reruns were used for the connmanager and peergov rows in this update.
|
|
53
|
+
- `Update Connection Metrics` now uses incremental cached counts instead of rescanning all connections.
|
|
54
|
+
- The default `serve/core` Badger profile now uses the previously measured Pi-tight cache sizing.
|
|
55
|
+
- `peergov.reconcile` still benefits heavily from keeping per-peer churn logs below `Info`.
|
|
56
|
+
- `peergov.reconcile` now reuses one reconcile timestamp and caches under-valency for warm-promotion candidates.
|
|
57
|
+
- `peergov.enforceStateLimit` now sorts only removable peers and rebuilds the slice once instead of repeatedly deleting from it.
|
|
58
|
+
- `peergov.reconcile` now skips valency-status scans entirely unless debug logging is enabled.
|
|
39
59
|
|
|
40
60
|
### Top Improvements
|
|
41
|
-
-
|
|
42
|
-
-
|
|
43
|
-
-
|
|
44
|
-
-
|
|
45
|
-
- ledger:
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
-
|
|
49
|
-
-
|
|
61
|
+
- connmanager:Update Connection Metrics/1000: `291625ns -> 30.09ns`
|
|
62
|
+
- connmanager:Update Connection Metrics/500: `138551ns -> 29.69ns`
|
|
63
|
+
- connmanager:Update Connection Metrics/100: `24518ns -> 29.82ns`
|
|
64
|
+
- connmanager:Update Connection Metrics/10: `3123ns -> 29.24ns`
|
|
65
|
+
- ledger:Blockfetch Near Tip Throughput: `86320ns -> 69818ns`
|
|
66
|
+
- ledger:Blockfetch Near Tip Throughput Predecoded: `40031ns -> 36428ns`
|
|
67
|
+
- peergov:Reconcile/1000: `2587803ns -> 1632793ns`
|
|
68
|
+
- peergov:Reconcile/500: `1072577ns -> 733098ns`
|
|
69
|
+
- peergov:Reconcile/100: `130667ns -> 93859ns`
|
|
50
70
|
|
|
51
71
|
|
|
52
72
|
## Historical Results
|
|
53
73
|
|
|
54
|
-
### March
|
|
74
|
+
### Earlier March 15, 2026 Baseline
|
|
55
75
|
|
|
56
76
|
| Benchmark | Iterations | Time/op | Extra Metrics | Memory/op | Allocs/op |
|
|
57
77
|
|-----------|------------|---------|---------------|-----------|-----------|
|
|
58
|
-
|
|
|
59
|
-
|
|
|
60
|
-
|
|
|
61
|
-
|
|
|
62
|
-
|
|
|
63
|
-
|
|
|
64
|
-
|
|
|
65
|
-
|
|
|
66
|
-
|
|
|
67
|
-
|
|
|
78
|
+
| connmanager:Has Inbound From Host/10 | 102497121 | 63.18ns | - | 0B | 0 |
|
|
79
|
+
| connmanager:Has Inbound From Host/100 | 93197125 | 57.95ns | - | 0B | 0 |
|
|
80
|
+
| connmanager:Has Inbound From Host/1000 | 99058254 | 60.09ns | - | 0B | 0 |
|
|
81
|
+
| connmanager:Has Inbound From Host/500 | 91016371 | 65.75ns | - | 0B | 0 |
|
|
82
|
+
| connmanager:Try Reserve Inbound Slot Parallel/10 | 15616777 | 403.8ns | - | 0B | 0 |
|
|
83
|
+
| connmanager:Try Reserve Inbound Slot Parallel/100 | 7449546 | 779.0ns | - | 0B | 0 |
|
|
84
|
+
| connmanager:Try Reserve Inbound Slot Parallel/500 | 7706102 | 772.6ns | - | 0B | 0 |
|
|
85
|
+
| connmanager:Update Connection Metrics/10 | 1876092 | 3123ns | - | 456B | 3 |
|
|
86
|
+
| connmanager:Update Connection Metrics/100 | 239965 | 24518ns | - | 3KB | 3 |
|
|
87
|
+
| connmanager:Update Connection Metrics/1000 | 20446 | 291625ns | - | 54KB | 5 |
|
|
88
|
+
| connmanager:Update Connection Metrics/500 | 43100 | 138551ns | - | 27KB | 3 |
|
|
89
|
+
| event:Publish Subscribers/1 | 7974799 | 650.6ns | - | 0B | 0 |
|
|
90
|
+
| event:Publish Subscribers/10 | 746738 | 7520ns | - | 0B | 0 |
|
|
91
|
+
| event:Publish Subscribers/100 | 61120 | 94657ns | - | 0B | 0 |
|
|
92
|
+
| event:Publish Subscribers/500 | 12976 | 489401ns | - | 0B | 0 |
|
|
93
|
+
| ledger:Block Processing Throughput | 54142 | 95123ns | 10513 blocks/sec | 25KB | 133 |
|
|
94
|
+
| ledger:Block Processing Throughput Predecoded | 144867 | 40441ns | 24728 blocks/sec | 2KB | 51 |
|
|
95
|
+
| ledger:Blockfetch Near Tip Throughput | 76536 | 86320ns | 11585 blocks/sec | 25KB | 128 |
|
|
96
|
+
| ledger:Blockfetch Near Tip Throughput Predecoded | 160242 | 40031ns | 24981 blocks/sec | 2KB | 50 |
|
|
97
|
+
| ledger:Blockfetch Verified Header Dispatch | 156298824 | 38.37ns | - | 0B | 0 |
|
|
98
|
+
| ledger:Verify Block Header/direct | 5907 | 1008310ns | - | 2KB | 29 |
|
|
99
|
+
| ledger:Verify Block Header/ledger_state | 5935 | 1006660ns | - | 2KB | 29 |
|
|
100
|
+
| peergov:Reconcile/100 | 45027 | 130667ns | - | 16KB | 185 |
|
|
101
|
+
| peergov:Reconcile/1000 | 2343 | 2587803ns | - | 202KB | 1662 |
|
|
102
|
+
| peergov:Reconcile/500 | 5739 | 1072577ns | - | 100KB | 760 |
|
package/generate_benchmarks.sh
CHANGED
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
|
|
3
|
+
set -euo pipefail
|
|
4
|
+
|
|
5
|
+
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
6
|
+
OUTPUT_FILE="${1:-benchmark_results_bp_pi.md}"
|
|
7
|
+
CACHE_DIR="${CACHE_DIR:-/tmp/dingo-bp-pi-go-cache}"
|
|
8
|
+
GOMAXPROCS_VALUE="${GOMAXPROCS_VALUE:-4}"
|
|
9
|
+
BENCH_TIME="${BENCH_TIME:-5s}"
|
|
10
|
+
IMMUTABLE_PATH="${IMMUTABLE_PATH:-database/immutable/testdata}"
|
|
11
|
+
DEFAULT_DB_DIR="${DEFAULT_DB_DIR:-}"
|
|
12
|
+
DEFAULT_LOG_FILE="${DEFAULT_LOG_FILE:-}"
|
|
13
|
+
DB_DIR_BASE="${DB_DIR_BASE:-/tmp}"
|
|
14
|
+
TMP_BENCH_FILE="$(mktemp)"
|
|
15
|
+
TIME_FORMAT_STYLE=""
|
|
16
|
+
TIME_CMD=()
|
|
17
|
+
AUTO_DEFAULT_DB_DIR=0
|
|
18
|
+
AUTO_DEFAULT_LOG_FILE=0
|
|
19
|
+
|
|
20
|
+
cleanup() {
|
|
21
|
+
local exit_status=$?
|
|
22
|
+
|
|
23
|
+
rm -f "$TMP_BENCH_FILE"
|
|
24
|
+
if [[ "$exit_status" -ne 0 ]]; then
|
|
25
|
+
if [[ "$AUTO_DEFAULT_LOG_FILE" -eq 1 ]]; then
|
|
26
|
+
printf 'preserving profile log for debugging: %s\n' \
|
|
27
|
+
"$DEFAULT_LOG_FILE" >&2
|
|
28
|
+
fi
|
|
29
|
+
if [[ "$AUTO_DEFAULT_DB_DIR" -eq 1 ]]; then
|
|
30
|
+
printf 'preserving profile database for debugging: %s\n' \
|
|
31
|
+
"$DEFAULT_DB_DIR" >&2
|
|
32
|
+
fi
|
|
33
|
+
return "$exit_status"
|
|
34
|
+
fi
|
|
35
|
+
|
|
36
|
+
if [[ "$AUTO_DEFAULT_LOG_FILE" -eq 1 ]]; then
|
|
37
|
+
rm -f "$DEFAULT_LOG_FILE"
|
|
38
|
+
fi
|
|
39
|
+
if [[ "$AUTO_DEFAULT_DB_DIR" -eq 1 ]]; then
|
|
40
|
+
rm -rf "$DEFAULT_DB_DIR"
|
|
41
|
+
fi
|
|
42
|
+
return "$exit_status"
|
|
43
|
+
}
|
|
44
|
+
trap cleanup EXIT
|
|
45
|
+
|
|
46
|
+
create_temp_dir() {
|
|
47
|
+
mktemp -d "${DB_DIR_BASE%/}/dingo-bp-pi-db-default.XXXXXX"
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
create_temp_file() {
|
|
51
|
+
mktemp "${DB_DIR_BASE%/}/dingo-bp-pi-default.XXXXXX.log"
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
resolve_path() {
|
|
55
|
+
local path="$1"
|
|
56
|
+
local current
|
|
57
|
+
local candidate
|
|
58
|
+
local part
|
|
59
|
+
local -a parts=()
|
|
60
|
+
|
|
61
|
+
if [[ -z "$path" ]]; then
|
|
62
|
+
return 1
|
|
63
|
+
fi
|
|
64
|
+
|
|
65
|
+
if [[ "$path" == /* ]]; then
|
|
66
|
+
current="/"
|
|
67
|
+
else
|
|
68
|
+
current="$(pwd -P)"
|
|
69
|
+
fi
|
|
70
|
+
|
|
71
|
+
local IFS='/'
|
|
72
|
+
read -r -a parts <<< "$path"
|
|
73
|
+
for part in "${parts[@]}"; do
|
|
74
|
+
case "$part" in
|
|
75
|
+
""|".")
|
|
76
|
+
continue
|
|
77
|
+
;;
|
|
78
|
+
"..")
|
|
79
|
+
if [[ "$current" != "/" ]]; then
|
|
80
|
+
current="${current%/*}"
|
|
81
|
+
if [[ -z "$current" ]]; then
|
|
82
|
+
current="/"
|
|
83
|
+
fi
|
|
84
|
+
fi
|
|
85
|
+
;;
|
|
86
|
+
*)
|
|
87
|
+
if [[ "$current" == "/" ]]; then
|
|
88
|
+
candidate="/$part"
|
|
89
|
+
else
|
|
90
|
+
candidate="$current/$part"
|
|
91
|
+
fi
|
|
92
|
+
if [[ -d "$candidate" ]]; then
|
|
93
|
+
current="$(cd "$candidate" && pwd -P)"
|
|
94
|
+
else
|
|
95
|
+
current="$candidate"
|
|
96
|
+
fi
|
|
97
|
+
;;
|
|
98
|
+
esac
|
|
99
|
+
done
|
|
100
|
+
|
|
101
|
+
printf '%s\n' "$current"
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
configure_time_cmd() {
|
|
105
|
+
if command -v gtime >/dev/null 2>&1 &&
|
|
106
|
+
gtime -f "elapsed=%e rss_kb=%M" true >/dev/null 2>&1; then
|
|
107
|
+
TIME_FORMAT_STYLE="gnu"
|
|
108
|
+
TIME_CMD=(gtime -f "elapsed=%e rss_kb=%M")
|
|
109
|
+
return 0
|
|
110
|
+
fi
|
|
111
|
+
|
|
112
|
+
if /usr/bin/time -f "elapsed=%e rss_kb=%M" true >/dev/null 2>&1; then
|
|
113
|
+
TIME_FORMAT_STYLE="gnu"
|
|
114
|
+
TIME_CMD=(/usr/bin/time -f "elapsed=%e rss_kb=%M")
|
|
115
|
+
return 0
|
|
116
|
+
fi
|
|
117
|
+
|
|
118
|
+
if /usr/bin/time -l true >/dev/null 2>&1; then
|
|
119
|
+
TIME_FORMAT_STYLE="bsd"
|
|
120
|
+
TIME_CMD=(/usr/bin/time -l)
|
|
121
|
+
return 0
|
|
122
|
+
fi
|
|
123
|
+
|
|
124
|
+
echo "error: failed to find a supported time command" >&2
|
|
125
|
+
return 1
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
validate_db_dir() {
|
|
129
|
+
local db_dir="$1"
|
|
130
|
+
local log_file="$2"
|
|
131
|
+
local resolved_db_dir
|
|
132
|
+
local resolved_base_dir
|
|
133
|
+
|
|
134
|
+
if [[ -z "$db_dir" || "$db_dir" == "/" || "$db_dir" == "." || "$db_dir" == "~" ]]; then
|
|
135
|
+
printf 'error: refusing to remove unsafe db_dir value %q\n' "$db_dir" >"$log_file"
|
|
136
|
+
return 1
|
|
137
|
+
fi
|
|
138
|
+
|
|
139
|
+
if ! resolved_db_dir="$(resolve_path "$db_dir")"; then
|
|
140
|
+
printf 'error: failed to resolve db_dir %q\n' "$db_dir" >"$log_file"
|
|
141
|
+
return 1
|
|
142
|
+
fi
|
|
143
|
+
if ! resolved_base_dir="$(resolve_path "$DB_DIR_BASE")"; then
|
|
144
|
+
printf 'error: failed to resolve DB_DIR_BASE %q\n' "$DB_DIR_BASE" >"$log_file"
|
|
145
|
+
return 1
|
|
146
|
+
fi
|
|
147
|
+
|
|
148
|
+
if [[ "$resolved_db_dir" == "$resolved_base_dir" ]]; then
|
|
149
|
+
printf 'error: refusing to remove db_dir %q because it resolves to the base directory %q\n' \
|
|
150
|
+
"$resolved_db_dir" "$resolved_base_dir" >"$log_file"
|
|
151
|
+
return 1
|
|
152
|
+
fi
|
|
153
|
+
|
|
154
|
+
case "$resolved_db_dir" in
|
|
155
|
+
"$resolved_base_dir"/*) ;;
|
|
156
|
+
*)
|
|
157
|
+
printf 'error: refusing to remove db_dir %q outside allowed base %q\n' \
|
|
158
|
+
"$resolved_db_dir" "$resolved_base_dir" >"$log_file"
|
|
159
|
+
return 1
|
|
160
|
+
;;
|
|
161
|
+
esac
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
extract_profile_line() {
|
|
165
|
+
local log_file="$1"
|
|
166
|
+
|
|
167
|
+
case "$TIME_FORMAT_STYLE" in
|
|
168
|
+
gnu)
|
|
169
|
+
awk '/elapsed=/{ line = $0 } END { print line }' "$log_file"
|
|
170
|
+
;;
|
|
171
|
+
bsd)
|
|
172
|
+
awk '
|
|
173
|
+
/^[[:space:]]*[0-9]+([.][0-9]+)?[[:space:]]+real([[:space:]]|$)/ {
|
|
174
|
+
elapsed = $1
|
|
175
|
+
}
|
|
176
|
+
/^[[:space:]]*[0-9]+[[:space:]]+maximum resident set size([[:space:]]|$)/ {
|
|
177
|
+
rss_kb = $1
|
|
178
|
+
}
|
|
179
|
+
END {
|
|
180
|
+
if (elapsed != "" || rss_kb != "") {
|
|
181
|
+
printf "elapsed=%s rss_kb=%s\n", elapsed, rss_kb
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
' "$log_file"
|
|
185
|
+
;;
|
|
186
|
+
*)
|
|
187
|
+
return 1
|
|
188
|
+
;;
|
|
189
|
+
esac
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
run_load_profile() {
|
|
193
|
+
local db_dir="$1"
|
|
194
|
+
local log_file="$2"
|
|
195
|
+
shift 2
|
|
196
|
+
|
|
197
|
+
validate_db_dir "$db_dir" "$log_file"
|
|
198
|
+
rm -rf "$db_dir"
|
|
199
|
+
: > "$log_file"
|
|
200
|
+
env -i \
|
|
201
|
+
PATH="$PATH" \
|
|
202
|
+
HOME="${HOME:-/tmp}" \
|
|
203
|
+
GOMAXPROCS="$GOMAXPROCS_VALUE" \
|
|
204
|
+
DINGO_RUN_MODE=serve \
|
|
205
|
+
DINGO_STORAGE_MODE=core \
|
|
206
|
+
"${TIME_CMD[@]}" \
|
|
207
|
+
./dingo \
|
|
208
|
+
--config /dev/null \
|
|
209
|
+
--blob badger \
|
|
210
|
+
--metadata sqlite \
|
|
211
|
+
--data-dir "$db_dir" \
|
|
212
|
+
load "$IMMUTABLE_PATH" "$@" \
|
|
213
|
+
> "$log_file" 2>&1
|
|
214
|
+
|
|
215
|
+
extract_profile_line "$log_file"
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
parse_metric() {
|
|
219
|
+
local line="$1"
|
|
220
|
+
local key="$2"
|
|
221
|
+
echo "$line" | awk -v needle="$key" '{
|
|
222
|
+
for (i = 1; i <= NF; i++) {
|
|
223
|
+
split($i, kv, "=")
|
|
224
|
+
if (kv[1] == needle) {
|
|
225
|
+
print kv[2]
|
|
226
|
+
exit
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
}'
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
configure_time_cmd
|
|
233
|
+
|
|
234
|
+
DB_DIR_BASE="$(resolve_path "$DB_DIR_BASE")"
|
|
235
|
+
|
|
236
|
+
if [[ -z "$DEFAULT_DB_DIR" ]]; then
|
|
237
|
+
DEFAULT_DB_DIR="$(create_temp_dir)"
|
|
238
|
+
AUTO_DEFAULT_DB_DIR=1
|
|
239
|
+
fi
|
|
240
|
+
|
|
241
|
+
if [[ -z "$DEFAULT_LOG_FILE" ]]; then
|
|
242
|
+
DEFAULT_LOG_FILE="$(create_temp_file)"
|
|
243
|
+
AUTO_DEFAULT_LOG_FILE=1
|
|
244
|
+
fi
|
|
245
|
+
|
|
246
|
+
pushd "$ROOT_DIR" >/dev/null
|
|
247
|
+
|
|
248
|
+
env \
|
|
249
|
+
GOCACHE="$CACHE_DIR" \
|
|
250
|
+
GOMAXPROCS="$GOMAXPROCS_VALUE" \
|
|
251
|
+
./generate_benchmarks.sh \
|
|
252
|
+
"$TMP_BENCH_FILE" \
|
|
253
|
+
--write \
|
|
254
|
+
--packages ./ledger \
|
|
255
|
+
--bench 'Benchmark(BlockfetchNearTipThroughput|BlockfetchNearTipThroughputPredecoded|BlockfetchNearTipQueuedHeaderPredecoded|BlockfetchNearTipFlushOnlyPredecoded|VerifyBlockHeader)$' \
|
|
256
|
+
--benchtime "$BENCH_TIME" \
|
|
257
|
+
--title "Four-Thread Block Producer Sizing Benchmark Results (Non-Pi Host)" \
|
|
258
|
+
--scope "Four-thread block producer path (GOMAXPROCS=${GOMAXPROCS_VALUE}) in core mode on a non-Pi host" \
|
|
259
|
+
--data-source "database/immutable/testdata plus local immutable load runs"
|
|
260
|
+
|
|
261
|
+
env \
|
|
262
|
+
GOCACHE="$CACHE_DIR" \
|
|
263
|
+
GOFLAGS=-buildvcs=false \
|
|
264
|
+
CGO_ENABLED=0 \
|
|
265
|
+
go build -o ./dingo ./cmd/dingo
|
|
266
|
+
|
|
267
|
+
default_line="$(run_load_profile "$DEFAULT_DB_DIR" "$DEFAULT_LOG_FILE")"
|
|
268
|
+
|
|
269
|
+
default_elapsed="$(parse_metric "$default_line" "elapsed")"
|
|
270
|
+
default_rss_kb="$(parse_metric "$default_line" "rss_kb")"
|
|
271
|
+
|
|
272
|
+
if [[ ! "$default_elapsed" =~ ^[0-9]+([.][0-9]+)?$ ]]; then
|
|
273
|
+
echo "error: failed to parse numeric elapsed value from $DEFAULT_LOG_FILE: ${default_elapsed:-<empty>}" >&2
|
|
274
|
+
exit 1
|
|
275
|
+
fi
|
|
276
|
+
if [[ ! "$default_rss_kb" =~ ^[0-9]+$ ]]; then
|
|
277
|
+
echo "error: failed to parse numeric rss_kb value from $DEFAULT_LOG_FILE: ${default_rss_kb:-<empty>}" >&2
|
|
278
|
+
exit 1
|
|
279
|
+
fi
|
|
280
|
+
|
|
281
|
+
default_rss_mb="$(awk "BEGIN { printf \"%.1f\", ${default_rss_kb} / 1024 }")"
|
|
282
|
+
|
|
283
|
+
{
|
|
284
|
+
echo "# Four-Thread Block Producer Sizing Report (Non-Pi Host)"
|
|
285
|
+
echo
|
|
286
|
+
echo "Assumptions:"
|
|
287
|
+
printf -- "- \`storageMode=core\`\n"
|
|
288
|
+
printf -- "- \`runMode=serve\`, \`blob=badger\`, \`metadata=sqlite\`\n"
|
|
289
|
+
printf -- "- \`GOMAXPROCS=%s\`\n" "$GOMAXPROCS_VALUE"
|
|
290
|
+
printf -- "- immutable fixture: \`%s\`\n" "$IMMUTABLE_PATH"
|
|
291
|
+
echo "- measurements were collected on non-Pi hardware and are a sizing proxy, not Raspberry Pi device benchmarks"
|
|
292
|
+
echo "- block producer peer count remains small; this is not a relay profile"
|
|
293
|
+
echo
|
|
294
|
+
echo "## Load Footprint"
|
|
295
|
+
echo
|
|
296
|
+
echo "| Profile | Elapsed | Peak RSS | Notes |"
|
|
297
|
+
echo "| --- | --- | --- | --- |"
|
|
298
|
+
printf -- "| \`core-default\` | \`%ss\` | \`%s MB\` | Current default \`serve/core\` cache profile |\n" "$default_elapsed" "$default_rss_mb"
|
|
299
|
+
echo
|
|
300
|
+
echo "## Recommendation"
|
|
301
|
+
echo
|
|
302
|
+
printf -- "For Raspberry Pi-class sizing in \`storageMode=core\`, the current default \`serve/core\` profile is already in the measured low-memory range on this four-thread non-Pi host.\n"
|
|
303
|
+
echo "Explicit Badger cache settings still override these defaults if an operator wants to tune further."
|
|
304
|
+
echo "Treat this as a sizing baseline rather than a direct Raspberry Pi hardware measurement."
|
|
305
|
+
echo
|
|
306
|
+
cat "$TMP_BENCH_FILE"
|
|
307
|
+
} > "$OUTPUT_FILE"
|
|
308
|
+
|
|
309
|
+
popd >/dev/null
|