-
Notifications
You must be signed in to change notification settings - Fork 468
fix(profiling): remove unnecessary access to frame.f_locals
#15434
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
|
|
KowalskiThomas
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch, this makes sense to me! 💯
Bootstrap import analysisComparison of import times between this PR and base. SummaryThe average import time from this PR is: 248 ± 3 ms. The average import time from base is: 252 ± 3 ms. The import time difference between this PR and base is: -4.5 ± 0.1 ms. Import time breakdownThe following import paths have shrunk:
|
Performance SLOsComparing candidate taegyunkim/prof-13153-pyframes-to-frame (b0ab10f) with baseline main (4753e14) 📈 Performance Regressions (2 suites)📈 iastaspectsospath - 24/24✅ ospathbasename_aspectTime: ✅ 5.056µs (SLO: <10.000µs 📉 -49.4%) vs baseline: 📈 +22.6% Memory: ✅ 40.364MB (SLO: <41.000MB 🟡 -1.6%) vs baseline: +4.9% ✅ ospathbasename_noaspectTime: ✅ 1.081µs (SLO: <10.000µs 📉 -89.2%) vs baseline: +0.1% Memory: ✅ 40.324MB (SLO: <41.000MB 🟡 -1.6%) vs baseline: +5.1% ✅ ospathjoin_aspectTime: ✅ 6.110µs (SLO: <10.000µs 📉 -38.9%) vs baseline: -0.8% Memory: ✅ 40.305MB (SLO: <41.000MB 🟡 -1.7%) vs baseline: +5.0% ✅ ospathjoin_noaspectTime: ✅ 2.283µs (SLO: <10.000µs 📉 -77.2%) vs baseline: -0.3% Memory: ✅ 40.462MB (SLO: <41.000MB 🟡 -1.3%) vs baseline: +5.1% ✅ ospathnormcase_aspectTime: ✅ 3.445µs (SLO: <10.000µs 📉 -65.5%) vs baseline: +1.4% Memory: ✅ 40.324MB (SLO: <41.000MB 🟡 -1.6%) vs baseline: +5.1% ✅ ospathnormcase_noaspectTime: ✅ 0.566µs (SLO: <10.000µs 📉 -94.3%) vs baseline: -0.9% Memory: ✅ 40.344MB (SLO: <41.000MB 🟡 -1.6%) vs baseline: +4.9% ✅ ospathsplit_aspectTime: ✅ 4.739µs (SLO: <10.000µs 📉 -52.6%) vs baseline: +0.7% Memory: ✅ 40.462MB (SLO: <41.000MB 🟡 -1.3%) vs baseline: +5.3% ✅ ospathsplit_noaspectTime: ✅ 1.602µs (SLO: <10.000µs 📉 -84.0%) vs baseline: +0.8% Memory: ✅ 40.285MB (SLO: <41.000MB 🟡 -1.7%) vs baseline: +4.8% ✅ ospathsplitdrive_aspectTime: ✅ 3.597µs (SLO: <10.000µs 📉 -64.0%) vs baseline: ~same Memory: ✅ 40.344MB (SLO: <41.000MB 🟡 -1.6%) vs baseline: +5.2% ✅ ospathsplitdrive_noaspectTime: ✅ 0.696µs (SLO: <10.000µs 📉 -93.0%) vs baseline: -0.4% Memory: ✅ 40.226MB (SLO: <41.000MB 🟡 -1.9%) vs baseline: +4.5% ✅ ospathsplitext_aspectTime: ✅ 4.495µs (SLO: <10.000µs 📉 -55.1%) vs baseline: +0.5% Memory: ✅ 40.423MB (SLO: <41.000MB 🟡 -1.4%) vs baseline: +5.0% ✅ ospathsplitext_noaspectTime: ✅ 1.384µs (SLO: <10.000µs 📉 -86.2%) vs baseline: -0.4% Memory: ✅ 40.226MB (SLO: <41.000MB 🟡 -1.9%) vs baseline: +4.9% 📈 telemetryaddmetric - 30/30✅ 1-count-metric-1-timesTime: ✅ 3.475µs (SLO: <20.000µs 📉 -82.6%) vs baseline: 📈 +18.8% Memory: ✅ 34.918MB (SLO: <35.500MB 🟡 -1.6%) vs baseline: +4.9% ✅ 1-count-metrics-100-timesTime: ✅ 204.311µs (SLO: <220.000µs -7.1%) vs baseline: +2.2% Memory: ✅ 34.977MB (SLO: <35.500MB 🟡 -1.5%) vs baseline: +5.2% ✅ 1-distribution-metric-1-timesTime: ✅ 3.319µs (SLO: <20.000µs 📉 -83.4%) vs baseline: +0.4% Memory: ✅ 34.918MB (SLO: <35.500MB 🟡 -1.6%) vs baseline: +5.0% ✅ 1-distribution-metrics-100-timesTime: ✅ 215.724µs (SLO: <230.000µs -6.2%) vs baseline: +0.6% Memory: ✅ 34.977MB (SLO: <35.500MB 🟡 -1.5%) vs baseline: +5.3% ✅ 1-gauge-metric-1-timesTime: ✅ 2.205µs (SLO: <20.000µs 📉 -89.0%) vs baseline: +0.6% Memory: ✅ 34.878MB (SLO: <35.500MB 🟡 -1.8%) vs baseline: +4.7% ✅ 1-gauge-metrics-100-timesTime: ✅ 137.325µs (SLO: <150.000µs -8.5%) vs baseline: -0.6% Memory: ✅ 34.937MB (SLO: <35.500MB 🟡 -1.6%) vs baseline: +4.9% ✅ 1-rate-metric-1-timesTime: ✅ 3.101µs (SLO: <20.000µs 📉 -84.5%) vs baseline: -0.2% Memory: ✅ 35.016MB (SLO: <35.500MB 🟡 -1.4%) vs baseline: +5.3% ✅ 1-rate-metrics-100-timesTime: ✅ 217.647µs (SLO: <250.000µs 📉 -12.9%) vs baseline: +1.3% Memory: ✅ 34.878MB (SLO: <35.500MB 🟡 -1.8%) vs baseline: +4.6% ✅ 100-count-metrics-100-timesTime: ✅ 20.363ms (SLO: <22.000ms -7.4%) vs baseline: +0.6% Memory: ✅ 34.819MB (SLO: <35.500MB 🟡 -1.9%) vs baseline: +4.6% ✅ 100-distribution-metrics-100-timesTime: ✅ 2.260ms (SLO: <2.300ms 🟡 -1.7%) vs baseline: -1.0% Memory: ✅ 35.016MB (SLO: <35.500MB 🟡 -1.4%) vs baseline: +5.0% ✅ 100-gauge-metrics-100-timesTime: ✅ 1.419ms (SLO: <1.550ms -8.5%) vs baseline: +0.4% Memory: ✅ 34.898MB (SLO: <35.500MB 🟡 -1.7%) vs baseline: +5.2% ✅ 100-rate-metrics-100-timesTime: ✅ 2.219ms (SLO: <2.550ms 📉 -13.0%) vs baseline: +0.5% Memory: ✅ 34.918MB (SLO: <35.500MB 🟡 -1.6%) vs baseline: +4.6% ✅ flush-1-metricTime: ✅ 4.400µs (SLO: <20.000µs 📉 -78.0%) vs baseline: -1.2% Memory: ✅ 35.291MB (SLO: <35.500MB 🟡 -0.6%) vs baseline: +5.0% ✅ flush-100-metricsTime: ✅ 173.591µs (SLO: <250.000µs 📉 -30.6%) vs baseline: +0.1% Memory: ✅ 35.232MB (SLO: <35.500MB 🟡 -0.8%) vs baseline: +4.5% ✅ flush-1000-metricsTime: ✅ 2.176ms (SLO: <2.500ms 📉 -13.0%) vs baseline: -0.5% Memory: ✅ 36.117MB (SLO: <36.500MB 🟡 -1.0%) vs baseline: +5.0% 🟡 Near SLO Breach (18 suites)🟡 coreapiscenario - 10/10 (1 unstable)
|
Description
We've been seeing a low number of crashes that have the following stack traces.
which corresponds to
value = frame.f_locals[argname]inextract_class_name()function.Fore more details see notebook, https://app.datadoghq.com/notebook/13515661/pyframe-to-frames-crashes
The reason this could lead to a crash is that the
framecould be in an invalid state, partially deallocated, or corrupted. And this doesn't happen on our stack sampler (Echion) as it doesn't use it, and just useco_qualname(Python 3.11+) orco_name(Python < 3.11)This code is no longer needed as we don't use
class_namefield fromDDFramenamed tuple. Memory profiler has been putting an empty string. Lock profiler populated it but then it didn't export it in the sample.More appropriate way to populate the class name for Python versions 3.11+ would be using
co_qualnameas Echion does. I'll follow up with this in a separate PR. And this is why we see fully qualified name on our CPU time view, but function name only on memory/lock views.CPU time view

Memory view

Testing
Risks
Additional Notes