The demo below simulates the core PGO insight: branch layout. A function has two outcomes — a hot path (the common case) and a cold path (the rare case). Without a profile the compiler places them in source order; with a profile it moves the hot path first so it falls through without a branch.
Drag the slider to set the percentage of calls that take the hot path, then press Run with profile to see how the compiler would reorder the code and estimate the cycle savings.
<!-- PGO branch-reorder demo: compare static (source-order) vs PGO (hot-first) layout -->
<p class="hint">Set the percentage of calls that take the <b>hot path</b> (the common case), then press <b>Run with profile</b>. The compiler moves the most-frequent branch to fall-through position, eliminating the branch-mispredict penalty for the common case.</p>
<div class="slider-row">
<label for="hotPct">Hot-path frequency: <strong id="hotVal">80</strong>%</label>
<input type="range" id="hotPct" min="0" max="100" value="80">
</div>
<div class="layout-area" id="layoutArea"></div>
<div class="status" id="status">Adjust the slider, then click Run.</div>
<div class="btns">
<button id="runBtn" type="button">Run with profile</button>
<button id="resetBtn" type="button" class="ghost">Reset</button>
</div>
/* Layout styles for branch boxes and status display */
* { box-sizing: border-box; }
body { font-family: system-ui, sans-serif; color: #222; margin: 0; }
.hint { font-size: .9rem; color: #444; margin: 0 0 .7rem; line-height: 1.45; }
.slider-row { display: flex; align-items: center; gap: .7rem; margin-bottom: .9rem; flex-wrap: wrap; }
.slider-row label { font-size: .9rem; min-width: 11rem; }
input[type=range] { flex: 1; min-width: 120px; max-width: 260px; }
.layout-area { display: flex; gap: 1.2rem; flex-wrap: wrap; margin: .4rem 0 .8rem; }
.layout-box { flex: 1; min-width: 180px; border: 1px solid #cdd9e3; border-radius: 10px; padding: .7rem .9rem; }
.layout-box h3 { margin: 0 0 .5rem; font-size: .85rem; text-transform: uppercase; letter-spacing: .06em; color: #555; }
.branch { display: flex; align-items: center; gap: .5rem; padding: .35rem .5rem; border-radius: 6px;
font: 600 .85rem ui-monospace, monospace; margin-bottom: .35rem; transition: all .3s; }
.branch.hot { background: #d0f0d8; border-left: 4px solid #1a7a3c; color: #155728; }
.branch.cold { background: #e8eef3; border-left: 4px solid #8da5b8; color: #3a5068; }
.branch .pct { margin-left: auto; font-size: .78rem; opacity: .75; }
.arrow { font-size: 1.1rem; }
.status { font-size: 1rem; font-weight: 600; margin: .4rem 0; min-height: 1.4em; }
.status.good { color: #0a7d33; }
.status.neutral { color: #555; }
button { font: 600 14px system-ui, sans-serif; padding: .45rem .9rem; border: 1px solid #1d3557;
background: #1d3557; color: #fff; border-radius: 8px; cursor: pointer; }
button.ghost { background: #fff; color: #1d3557; }
.btns { display: flex; gap: .5rem; flex-wrap: wrap; }
.savings-bar { height: 10px; border-radius: 5px; background: #c3e6cb; margin-top: .4rem; transition: width .5s; }
const i18nFmt = (s, v) => s.replace(/%(\w+)%/g, (_, k) => String(v[k] ?? ''));
/* Branch mispredict penalty in cycles (typical modern CPU) */
const MISPREDICT_CYCLES = 15;
/* Calculate expected penalty per call with and without PGO */
function calcSavings(hotPct) {
/* Without PGO: cold branch is in fall-through position (source order) */
/* The cold branch falls through unconditionally — mispredicted whenever the hot path runs */
const hotFreq = hotPct / 100;
const coldFreq = 1 - hotFreq;
/* Expected penalty per call: cold-path frequency * full mispredict cost */
const mispredWithout = coldFreq * MISPREDICT_CYCLES;
/* With PGO: hot branch is in fall-through position */
/* The predictor almost never mispredicts a fall-through; residual cost modeled as 0.5 cycles */
const mispredWith = coldFreq * 0.5;
/* Savings = penalty removed by putting the common branch in fall-through */
const delta = mispredWithout - mispredWith;
return { mispredWithout, mispredWith, delta, hotFreq, coldFreq };
}
function renderLayouts(hotPct) {
const area = document.getElementById('layoutArea');
area.innerHTML = '';
/* Left column: static / source-order layout */
const staticBox = document.createElement('div');
staticBox.className = 'layout-box';
staticBox.innerHTML =
'<h3>Without PGO (source order)</h3>' +
'<div class="branch hot"><span class="arrow">→</span>HOT path<span class="pct">' + hotPct + '%</span></div>' +
'<div class="branch cold"><span class="arrow">→</span>COLD path<span class="pct">' + (100 - hotPct) + '%</span></div>';
area.appendChild(staticBox);
/* Right column: PGO-driven layout (most frequent path gets fall-through) */
const pgoBox = document.createElement('div');
pgoBox.className = 'layout-box';
if (hotPct >= 50) {
/* Hot path is more common — move it to fall-through (no branch) */
pgoBox.innerHTML =
'<h3>With PGO (profile-driven)</h3>' +
'<div class="branch hot"><span class="arrow">↓</span>HOT path<span class="pct">' + hotPct + '%</span></div>' +
'<div class="branch cold"><span class="arrow">→</span>COLD path<span class="pct">' + (100 - hotPct) + '%</span></div>';
} else {
/* Cold path is more common — move it to fall-through instead */
pgoBox.innerHTML =
'<h3>With PGO (profile-driven)</h3>' +
'<div class="branch cold"><span class="arrow">↓</span>COLD path<span class="pct">' + (100 - hotPct) + '%</span></div>' +
'<div class="branch hot"><span class="arrow">→</span>HOT path<span class="pct">' + hotPct + '%</span></div>';
}
area.appendChild(pgoBox);
}
function run() {
const hotPct = parseInt(document.getElementById('hotPct').value, 10);
const { mispredWithout, mispredWith, delta, hotFreq, coldFreq } = calcSavings(hotPct);
renderLayouts(hotPct);
const pct = mispredWithout > 0 ? Math.round((delta / mispredWithout) * 100) : 0;
const st = document.getElementById('status');
if (hotPct === 50) {
st.textContent = '50 / 50 split — both layouts are equivalent, no gain.';
st.className = 'status neutral';
} else {
st.textContent = i18nFmt('PGO eliminates ~%pct% of branch-mispredict penalties for this workload.', { pct: pct });
st.className = 'status good';
}
}
function reset() {
document.getElementById('hotPct').value = 80;
document.getElementById('hotVal').textContent = '80';
renderLayouts(80);
document.getElementById('status').textContent = 'Adjust the slider, then click Run.';
document.getElementById('status').className = 'status neutral';
}
document.getElementById('hotPct').addEventListener('input', function () {
document.getElementById('hotVal').textContent = this.value;
renderLayouts(parseInt(this.value, 10));
});
document.getElementById('runBtn').addEventListener('click', run);
document.getElementById('resetBtn').addEventListener('click', reset);
/* Initial render on page load */
renderLayouts(80);
document.getElementById('status').className = 'status neutral';
<!-- PGO branch-reorder demo: compare static (source-order) vs PGO (hot-first) layout -->
<p class="hint">Set the percentage of calls that take the <b>hot path</b> (the common case), then press <b>Run with profile</b>. The compiler moves the most-frequent branch to fall-through position, eliminating the branch-mispredict penalty for the common case.</p>
<div class="slider-row">
<label for="hotPct">Hot-path frequency: <strong id="hotVal">80</strong>%</label>
<input type="range" id="hotPct" min="0" max="100" value="80">
</div>
<div class="layout-area" id="layoutArea"></div>
<div class="status" id="status">Adjust the slider, then click Run.</div>
<div class="btns">
<button id="runBtn" type="button">Run with profile</button>
<button id="resetBtn" type="button" class="ghost">Reset</button>
</div>
/* Layout styles for branch boxes and status display */
* { box-sizing: border-box; }
body { font-family: system-ui, sans-serif; color: #222; margin: 0; }
.hint { font-size: .9rem; color: #444; margin: 0 0 .7rem; line-height: 1.45; }
.slider-row { display: flex; align-items: center; gap: .7rem; margin-bottom: .9rem; flex-wrap: wrap; }
.slider-row label { font-size: .9rem; min-width: 11rem; }
input[type=range] { flex: 1; min-width: 120px; max-width: 260px; }
.layout-area { display: flex; gap: 1.2rem; flex-wrap: wrap; margin: .4rem 0 .8rem; }
.layout-box { flex: 1; min-width: 180px; border: 1px solid #cdd9e3; border-radius: 10px; padding: .7rem .9rem; }
.layout-box h3 { margin: 0 0 .5rem; font-size: .85rem; text-transform: uppercase; letter-spacing: .06em; color: #555; }
.branch { display: flex; align-items: center; gap: .5rem; padding: .35rem .5rem; border-radius: 6px;
font: 600 .85rem ui-monospace, monospace; margin-bottom: .35rem; transition: all .3s; }
.branch.hot { background: #d0f0d8; border-left: 4px solid #1a7a3c; color: #155728; }
.branch.cold { background: #e8eef3; border-left: 4px solid #8da5b8; color: #3a5068; }
.branch .pct { margin-left: auto; font-size: .78rem; opacity: .75; }
.arrow { font-size: 1.1rem; }
.status { font-size: 1rem; font-weight: 600; margin: .4rem 0; min-height: 1.4em; }
.status.good { color: #0a7d33; }
.status.neutral { color: #555; }
button { font: 600 14px system-ui, sans-serif; padding: .45rem .9rem; border: 1px solid #1d3557;
background: #1d3557; color: #fff; border-radius: 8px; cursor: pointer; }
button.ghost { background: #fff; color: #1d3557; }
.btns { display: flex; gap: .5rem; flex-wrap: wrap; }
.savings-bar { height: 10px; border-radius: 5px; background: #c3e6cb; margin-top: .4rem; transition: width .5s; }
const i18nFmt = (s, v) => s.replace(/%(\w+)%/g, (_, k) => String(v[k] ?? ''));
/* Branch mispredict penalty in cycles (typical modern CPU) */
const MISPREDICT_CYCLES = 15;
/* Calculate expected penalty per call with and without PGO */
function calcSavings(hotPct) {
/* Without PGO: cold branch is in fall-through position (source order) */
/* The cold branch falls through unconditionally — mispredicted whenever the hot path runs */
const hotFreq = hotPct / 100;
const coldFreq = 1 - hotFreq;
/* Expected penalty per call: cold-path frequency * full mispredict cost */
const mispredWithout = coldFreq * MISPREDICT_CYCLES;
/* With PGO: hot branch is in fall-through position */
/* The predictor almost never mispredicts a fall-through; residual cost modeled as 0.5 cycles */
const mispredWith = coldFreq * 0.5;
/* Savings = penalty removed by putting the common branch in fall-through */
const delta = mispredWithout - mispredWith;
return { mispredWithout, mispredWith, delta, hotFreq, coldFreq };
}
function renderLayouts(hotPct) {
const area = document.getElementById('layoutArea');
area.innerHTML = '';
/* Left column: static / source-order layout */
const staticBox = document.createElement('div');
staticBox.className = 'layout-box';
staticBox.innerHTML =
'<h3>Without PGO (source order)</h3>' +
'<div class="branch hot"><span class="arrow">→</span>HOT path<span class="pct">' + hotPct + '%</span></div>' +
'<div class="branch cold"><span class="arrow">→</span>COLD path<span class="pct">' + (100 - hotPct) + '%</span></div>';
area.appendChild(staticBox);
/* Right column: PGO-driven layout (most frequent path gets fall-through) */
const pgoBox = document.createElement('div');
pgoBox.className = 'layout-box';
if (hotPct >= 50) {
/* Hot path is more common — move it to fall-through (no branch) */
pgoBox.innerHTML =
'<h3>With PGO (profile-driven)</h3>' +
'<div class="branch hot"><span class="arrow">↓</span>HOT path<span class="pct">' + hotPct + '%</span></div>' +
'<div class="branch cold"><span class="arrow">→</span>COLD path<span class="pct">' + (100 - hotPct) + '%</span></div>';
} else {
/* Cold path is more common — move it to fall-through instead */
pgoBox.innerHTML =
'<h3>With PGO (profile-driven)</h3>' +
'<div class="branch cold"><span class="arrow">↓</span>COLD path<span class="pct">' + (100 - hotPct) + '%</span></div>' +
'<div class="branch hot"><span class="arrow">→</span>HOT path<span class="pct">' + hotPct + '%</span></div>';
}
area.appendChild(pgoBox);
}
function run() {
const hotPct = parseInt(document.getElementById('hotPct').value, 10);
const { mispredWithout, mispredWith, delta, hotFreq, coldFreq } = calcSavings(hotPct);
renderLayouts(hotPct);
const pct = mispredWithout > 0 ? Math.round((delta / mispredWithout) * 100) : 0;
const st = document.getElementById('status');
if (hotPct === 50) {
st.textContent = '50 / 50 split — both layouts are equivalent, no gain.';
st.className = 'status neutral';
} else {
st.textContent = i18nFmt('PGO eliminates ~%pct% of branch-mispredict penalties for this workload.', { pct: pct });
st.className = 'status good';
}
}
function reset() {
document.getElementById('hotPct').value = 80;
document.getElementById('hotVal').textContent = '80';
renderLayouts(80);
document.getElementById('status').textContent = 'Adjust the slider, then click Run.';
document.getElementById('status').className = 'status neutral';
}
document.getElementById('hotPct').addEventListener('input', function () {
document.getElementById('hotVal').textContent = this.value;
renderLayouts(parseInt(this.value, 10));
});
document.getElementById('runBtn').addEventListener('click', run);
document.getElementById('resetBtn').addEventListener('click', reset);
/* Initial render on page load */
renderLayouts(80);
document.getElementById('status').className = 'status neutral';
Notice that when the hot path is taken 95 % of the time, reordering it first eliminates almost every branch-mispredict penalty. When calls split 50/50, the two layouts are equivalent — no profile can help.
Comments
Loading comments...