Skip to content

Commit 42f21ae

Browse files
feat: restore edge/block collection and runtime consumption (#10869)
* feat: restore edge/block PGO collection and runtime consumption Re-enable DOTNET_WritePGOData in Dockerfile.pgo to collect JIT edge/block profiling data during PGO runs. Add PgoTrim tool to strip cold methods and compress the ~31MB .jit file to ~438KB gzip. The weekly workflow now trims and commits nethermind.jit.gz alongside the .mibc profile. The production Dockerfile decompresses the .jit.gz at build time, and entrypoint.sh enables DOTNET_ReadPGOData when the file exists, giving the JIT branch layout hints and guarded devirtualization data. * chore(pgo): update PGO profile (#10870) chore(pgo): update PGO profile from weekly collection Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> * chore(pgo): update PGO profile (#10870) chore(pgo): update PGO profile from weekly collection Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> * fix: address PGO pipeline review feedback - Flush pending histogram count at method boundaries in PgoTrim to prevent silent data loss if kind-177 has no paired 195/196 - Use [ -s ] instead of [ -f ] in Dockerfile so empty .jit.gz placeholder does not fail gzip decompression - Log when edge/block PGO is enabled in entrypoint.sh for operator visibility - Update Dockerfile.pgo header comment to mention both .nettrace and .jit outputs * fix: use proper nullable tuple pattern in PgoTrim Replace `is var (x, y)` (always matches, even when null) with `is (string x, string y)` so pending histogram entries are only emitted when actually present. * chore: default reproducible benchmarks to flat db layout --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
1 parent 344edcc commit 42f21ae

File tree

9 files changed

+393
-4
lines changed

9 files changed

+393
-4
lines changed

.github/workflows/collect-pgo-profile.yml

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,8 @@ jobs:
247247
248248
echo "=== .nettrace files (EventPipe method traces) ==="
249249
find "${RUNNER_TEMP}/pgo-data" -name "*.nettrace" -type f -ls 2>/dev/null || true
250+
echo "=== .jit files (edge/block profiling data) ==="
251+
find "${RUNNER_TEMP}/pgo-data" -name "*.jit" -type f -ls 2>/dev/null || true
250252
251253
- name: Set up .NET
252254
if: always()
@@ -334,6 +336,20 @@ jobs:
334336
ls -lh "${mibc_file}"
335337
echo "mibc_file=${mibc_file}" >> "${GITHUB_OUTPUT}"
336338
339+
# Step 2: Trim .jit edge/block profiling data for runtime PGO
340+
# .jit files (from DOTNET_WritePGOData) use a JIT-internal text format read
341+
# back via DOTNET_ReadPGOData — they can't be merged into .mibc by dotnet-pgo.
342+
jit_file=$(find "${pgo_dir}" -name "*.jit" -type f -printf '%T@ %p\n' 2>/dev/null | sort -nr | head -1 | cut -d' ' -f2- || true)
343+
jit_gz="${RUNNER_TEMP}/nethermind.jit.gz"
344+
if [[ -n "${jit_file}" ]]; then
345+
echo "Trimming ${jit_file} with PgoTrim..."
346+
dotnet run --project "${GITHUB_WORKSPACE}/tools/PgoTrim" -c Release -- \
347+
"${jit_file}" "${jit_gz}" --min-block 100 --min-edge 250
348+
echo "jit_gz=${jit_gz}" >> "${GITHUB_OUTPUT}"
349+
else
350+
echo "No .jit file found — skipping edge profiling trim."
351+
fi
352+
337353
- name: Upload .mibc artifact
338354
if: always()
339355
uses: actions/upload-artifact@v7
@@ -342,6 +358,14 @@ jobs:
342358
path: ${{ steps.convert.outputs.mibc_file }}
343359
retention-days: 90
344360

361+
- name: Upload trimmed .jit.gz artifact
362+
if: always() && steps.convert.outputs.jit_gz != ''
363+
uses: actions/upload-artifact@v7
364+
with:
365+
name: nethermind-pgo-jit
366+
path: ${{ steps.convert.outputs.jit_gz }}
367+
retention-days: 90
368+
345369
- name: Upload raw PGO data
346370
if: always()
347371
uses: actions/upload-artifact@v7
@@ -366,10 +390,17 @@ jobs:
366390
name: nethermind-pgo-profile
367391
path: src/Nethermind/Nethermind.Runner/pgo/
368392

393+
- name: Download .jit.gz artifact
394+
uses: actions/download-artifact@v7
395+
continue-on-error: true
396+
with:
397+
name: nethermind-pgo-jit
398+
path: src/Nethermind/Nethermind.Runner/pgo/
399+
369400
- name: Check for changes
370401
id: diff
371402
run: |
372-
if git diff --quiet src/Nethermind/Nethermind.Runner/pgo/nethermind.mibc; then
403+
if git diff --quiet src/Nethermind/Nethermind.Runner/pgo/; then
373404
echo "changed=false" >> "${GITHUB_OUTPUT}"
374405
echo "No changes to PGO profile."
375406
else
@@ -387,13 +418,15 @@ jobs:
387418
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
388419
git checkout -b "${branch}"
389420
git add src/Nethermind/Nethermind.Runner/pgo/nethermind.mibc
421+
git add src/Nethermind/Nethermind.Runner/pgo/nethermind.jit.gz 2>/dev/null || true
390422
git commit -m "chore(pgo): update PGO profile from weekly collection"
391423
git push -u origin "${branch}"
392424
gh pr create \
393425
--title "chore(pgo): update PGO profile" \
394426
--body "$(cat <<'EOF'
395427
## Summary
396428
- Weekly automated update of the PGO (.mibc) profile used for R2R compilation
429+
- Updated edge/block profiling data (.jit.gz) for runtime branch optimization
397430
- Generated from 5000 mainnet blocks via EventPipe profiling
398431
399432
## Test plan

.github/workflows/run-expb-reproducible-benchmarks.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ on:
1818
options:
1919
- halfpath
2020
- flat
21-
default: halfpath
21+
default: flat
2222
payload_set:
2323
description: Payload set mode
2424
required: true
@@ -168,7 +168,7 @@ jobs:
168168
should_run="false"
169169
fi
170170
branch="${PR_HEAD_BRANCH}"
171-
state_layout="halfpath"
171+
state_layout="flat"
172172
payload_set="superblocks"
173173
payload_sets='["superblocks","realblocks"]'
174174
expb_repo="NethermindEth/execution-payloads-benchmarks"
@@ -181,7 +181,7 @@ jobs:
181181
run_count="1"
182182
else
183183
branch="${PUSH_BRANCH}"
184-
state_layout="halfpath"
184+
state_layout="flat"
185185
payload_set="superblocks"
186186
payload_sets='["superblocks","realblocks"]'
187187
expb_repo="NethermindEth/execution-payloads-benchmarks"

Dockerfile

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,15 @@ FROM mcr.microsoft.com/dotnet/aspnet:10.0.5-noble@sha256:a04d1c1d2d2611904949405
3030

3131
WORKDIR /nethermind
3232

33+
# Decompress edge/block PGO data for runtime JIT optimization
34+
# The .jit.gz is generated by the weekly PGO collection workflow
35+
COPY src/Nethermind/Nethermind.Runner/pgo/ /tmp/pgo/
36+
RUN mkdir -p pgo && \
37+
if [ -s /tmp/pgo/nethermind.jit.gz ]; then \
38+
gzip -d -c /tmp/pgo/nethermind.jit.gz > pgo/nethermind.jit; \
39+
fi && \
40+
rm -rf /tmp/pgo
41+
3342
VOLUME /nethermind/keystore
3443
VOLUME /nethermind/logs
3544
VOLUME /nethermind/nethermind_db

Dockerfile.pgo

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
# Builds Nethermind WITHOUT ReadyToRun so the JIT compiles all methods,
55
# then enables EventPipe to collect profile data for Static PGO.
66
# The resulting .nettrace file is converted to .mibc offline.
7+
# Also writes edge/block profiling data (.jit) via DOTNET_WritePGOData
8+
# which is trimmed by PgoTrim and consumed at runtime via DOTNET_ReadPGOData.
79

810
FROM --platform=$BUILDPLATFORM mcr.microsoft.com/dotnet/sdk:10.0.201-noble@sha256:478b9038d187e5b5c29bfa8173ded5d29e864b5ad06102a12106380ee01e2e49 AS build
911

@@ -47,6 +49,10 @@ ENV DOTNET_EnableEventPipe=1
4749
ENV DOTNET_EventPipeCircularMB=256
4850
ENV DOTNET_EventPipeOutputPath=/nethermind/pgo/nethermind-{pid}.nettrace
4951
ENV DOTNET_EventPipeConfig=Microsoft-Windows-DotNETRuntime:0x1E000080018:4
52+
# Write edge/block profiling data after Tier-1 compilation for branch optimization
53+
ENV DOTNET_TieredPGO=1
54+
ENV DOTNET_WritePGOData=1
55+
ENV DOTNET_PGODataPath=/nethermind/pgo/nethermind.jit
5056

5157
VOLUME /nethermind/keystore
5258
VOLUME /nethermind/logs

scripts/entrypoint.sh

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,4 +66,11 @@ if [[ -z "${DOTNET_GCLargePages:-}" ]]; then
6666
fi
6767
fi
6868

69+
# Enable edge/block PGO if the trimmed profile exists
70+
if [[ -z "${DOTNET_ReadPGOData:-}" ]] && [[ -f "/nethermind/pgo/nethermind.jit" ]]; then
71+
export DOTNET_ReadPGOData=1
72+
export DOTNET_PGODataPath=/nethermind/pgo/nethermind.jit
73+
echo "Edge/block PGO enabled: ${DOTNET_PGODataPath}"
74+
fi
75+
6976
exec ./nethermind "$@"
432 KB
Binary file not shown.
-118 Bytes
Binary file not shown.

tools/PgoTrim/PgoTrim.csproj

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
<PropertyGroup>
3+
<OutputType>Exe</OutputType>
4+
</PropertyGroup>
5+
</Project>

0 commit comments

Comments
 (0)