Skip to content

Commit 5291b52

Browse files
committed
Add missing samples
1 parent 870b164 commit 5291b52

4 files changed

Lines changed: 32 additions & 7 deletions

File tree

Lib/profiling/sampling/flamegraph.js

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ function toggleSidebar() {
7676
const sidebar = document.getElementById('sidebar');
7777
if (sidebar) {
7878
const isCollapsing = !sidebar.classList.contains('collapsed');
79-
79+
8080
if (isCollapsing) {
8181
// Save current width before collapsing
8282
const currentWidth = sidebar.offsetWidth;
@@ -89,7 +89,7 @@ function toggleSidebar() {
8989
sidebar.style.width = savedWidth + 'px';
9090
}
9191
}
92-
92+
9393
sidebar.classList.toggle('collapsed');
9494
localStorage.setItem('flamegraph-sidebar', sidebar.classList.contains('collapsed') ? 'collapsed' : 'expanded');
9595

@@ -558,11 +558,11 @@ function initSidebarResize() {
558558
isResizing = false;
559559
resizeHandle.classList.remove('resizing');
560560
document.body.classList.remove('resizing-sidebar');
561-
561+
562562
// Save the new width
563563
const width = sidebar.offsetWidth;
564564
localStorage.setItem('flamegraph-sidebar-width', width);
565-
565+
566566
// Resize chart after sidebar resize
567567
setTimeout(() => {
568568
resizeChart();
@@ -666,6 +666,7 @@ function populateProfileSummary(data) {
666666
const duration = stats.duration_sec || 0;
667667
const sampleRate = stats.sample_rate || (duration > 0 ? totalSamples / duration : 0);
668668
const errorRate = stats.error_rate || 0;
669+
const missedSamples= stats.missed_samples || 0;
669670

670671
const samplesEl = document.getElementById('stat-total-samples');
671672
if (samplesEl) samplesEl.textContent = formatNumber(totalSamples);
@@ -701,6 +702,19 @@ function populateProfileSummary(data) {
701702
const efficiencyFill = document.getElementById('efficiency-fill');
702703
if (efficiencyFill) efficiencyFill.style.width = efficiency + '%';
703704
}
705+
// MissedSamples bar
706+
if (missedSamples !== undefined && missedSamples !== null) {
707+
const sampleEfficiency = Math.max(0, missedSamples);
708+
709+
const efficiencySection = document.getElementById('efficiency-section');
710+
if (efficiencySection) efficiencySection.style.display = 'block';
711+
712+
const sampleEfficiencyValue = document.getElementById('stat-missed-samples');
713+
if (sampleEfficiencyValue) sampleEfficiencyValue.textContent = sampleEfficiency.toFixed(1) + '%';
714+
715+
const sampleEfficiencyFill = document.getElementById('missed-samples-fill');
716+
if (sampleEfficiencyFill) sampleEfficiencyFill.style.width = sampleEfficiency + '%';
717+
}
704718
}
705719

706720
// ============================================================================

Lib/profiling/sampling/flamegraph_template.html

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,14 @@ <h3 class="section-title">Profile Summary</h3>
123123
<div class="efficiency-bar">
124124
<div class="efficiency-fill" id="efficiency-fill"></div>
125125
</div>
126+
<div class="missed-samples-header">
127+
<span class="efficiency-label">Missed samples</span>
128+
<span class="efficiency-value" id="stat-missed-samples">--</span>
129+
</div>
130+
<div class="efficiency-bar">
131+
<div class="efficiency-fill" id="missed-samples-fill"></div>
132+
</div>
133+
126134
</div>
127135
</div>
128136
</section>

Lib/profiling/sampling/sample.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,8 @@ def sample(self, collector, duration_sec=10):
108108

109109
sample_rate = num_samples / running_time
110110
error_rate = (errors / num_samples) * 100 if num_samples > 0 else 0
111+
expected_samples = int(duration_sec / sample_interval_sec)
112+
missed_samples = (expected_samples - num_samples) / expected_samples * 100
111113

112114
# Don't print stats for live mode (curses is handling display)
113115
is_live_mode = LiveStatsCollector is not None and isinstance(collector, LiveStatsCollector)
@@ -118,9 +120,8 @@ def sample(self, collector, duration_sec=10):
118120

119121
# Pass stats to flamegraph collector if it's the right type
120122
if hasattr(collector, 'set_stats'):
121-
collector.set_stats(self.sample_interval_usec, running_time, sample_rate, error_rate, mode=self.mode)
123+
collector.set_stats(self.sample_interval_usec, running_time, sample_rate, error_rate, missed_samples, mode=self.mode)
122124

123-
expected_samples = int(duration_sec / sample_interval_sec)
124125
if num_samples < expected_samples and not is_live_mode:
125126
print(
126127
f"Warning: missed {expected_samples - num_samples} samples "

Lib/profiling/sampling/stack_collector.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,13 +113,15 @@ def collect(self, stack_frames, skip_idle=False):
113113
# Call parent collect to process frames
114114
super().collect(stack_frames, skip_idle=skip_idle)
115115

116-
def set_stats(self, sample_interval_usec, duration_sec, sample_rate, error_rate=None, mode=None):
116+
def set_stats(self, sample_interval_usec, duration_sec, sample_rate,
117+
error_rate=None, missed_samples=None, mode=None):
117118
"""Set profiling statistics to include in flamegraph data."""
118119
self.stats = {
119120
"sample_interval_usec": sample_interval_usec,
120121
"duration_sec": duration_sec,
121122
"sample_rate": sample_rate,
122123
"error_rate": error_rate,
124+
"missed_samples": missed_samples,
123125
"mode": mode
124126
}
125127

0 commit comments

Comments
 (0)