Skip to content

Limit Dev18 Python profiling to Python 3.12-3.14 - #8598

Merged
StellaHuang95 merged 2 commits into
microsoft:mainfrom
StellaHuang95:drop-python39-311-profiling
Jul 30, 2026
Merged

Limit Dev18 Python profiling to Python 3.12-3.14#8598
StellaHuang95 merged 2 commits into
microsoft:mainfrom
StellaHuang95:drop-python39-311-profiling

Conversation

@StellaHuang95

Copy link
Copy Markdown
Contributor

Context

Python profiling is currently unavailable in Dev18 because the legacy PTVS path depends on VSPerfMon.exe and VSPerfCmd.exe, which are no longer shipped. #8591 began an exploratory effort to make profiling work again by routing PTVS through the Diagnostics Hub Python target and microsoft/python-etwtrace.

This is exploratory enablement rather than a regression in a working Dev18 user scenario. We have no known user complaints about Dev18 Python profiling, and the feature was already broken before this work. The priority is therefore to establish a reliable, supportable path for current Python versions rather than restore every historical interpreter at substantially higher release and compliance cost.

Why PTVS originally included two etwtrace versions

etwtrace contains native .pyd extensions compiled for specific CPython ABIs. A cp312 extension cannot load into Python 3.11, for example.

  • etwtrace 0.1b8 is the last release that contains wheels for Python 3.9, 3.10, and 3.11. PTVS installed it into a separate etwtrace_legacy directory and used extra collector-loading compatibility code for those interpreters.
  • etwtrace 0.1b9 contains the current Python 3.12, 3.13, and 3.14 wheels and is the payload used by the new Diagnostics Hub path.

The bootstrap selected the legacy directory for Python 3.9-3.11 and the current directory for Python 3.12-3.14.

Why the insertion failed

The Dev18 insertion SymbolCheck found 24 newly introduced native binaries under etwtrace_legacy:

  • Eight etwtrace 0.1b8 Windows wheels were merged into the legacy payload.
  • Each wheel contains three native extensions: _etwtrace, _etwinstrument, and _vsinstrument.
  • The wheels contain no matching PDB files.
  • PTVS's symbol archival step only stages explicitly listed PTVS build outputs; it never staged these prebuilt dependency binaries or their symbols.
  • The Windows PDB identities embedded in the 24 .pyd files are not archived on MSDL.

As a result, the PTVS build and release could succeed while the Visual Studio insertion correctly failed its symbol policy. This is not a transient policy issue or a portable-PDB false positive; the exact Windows PDBs required by the shipped binaries are unavailable to the insertion.

What would be required to keep Python 3.9-3.11 profiling

Adding *.pyd to PTVS's symbol publishing list is not sufficient because the matching PDBs are absent. A compliant legacy payload would require one of the following:

  1. Recover the exact PDBs produced alongside the published 0.1b8 wheels and archive each matching .pyd/PDB pair to MSDL.
  2. If those artifacts no longer exist, produce a new legacy etwtrace release from the 0.1b8 line:
    • Build the required CPython 3.9-3.11 architecture matrix in an official pipeline.
    • Retain the exact Windows PDB generated for every .pyd.
    • Sign and publish the new wheel binaries.
    • Archive the matching binary/PDB pairs before insertion.
    • Publish the new version to the approved internal feed and update PTVS to consume it.
    • Filter the legacy restore so it does not also package the unnecessary Python 3.12 and 3.13 wheels from 0.1b8.

That is primarily a producer/release-pipeline investment, not a small PTVS packaging fix. It also preserves a second native payload and compatibility path indefinitely.

Changes

  • Remove the etwtrace 0.1b8 restore and the etwtrace_legacy VSIX payload.
  • Package only etwtrace 0.1b9 for Python 3.12-3.14.
  • Remove the legacy collector compatibility path from diaghub_profile.py.
  • Make the Python bootstrap explicitly reject versions outside 3.12-3.14.
  • Probe the selected interpreter version before returning a command to Diagnostics Hub.
    • Python 3.9-3.11 now receives a clear warning with the detected version and supported range.
    • PTVS returns no launch command, so Diagnostics Hub does not create an empty session.
    • An invalid or unreadable interpreter also produces an actionable error instead of starting a session that cannot collect data.
  • Keep the Python-side version check as a defense-in-depth guard.

Why this is the best fix for the exploratory item

  • It restores a reliable path for the currently supported Python 3.12-3.14 matrix.
  • It avoids bypassing a valid symbol-compliance failure.
  • It removes 24 unarchived native binaries and the old collector compatibility path.
  • It avoids investing in reconstruction of a 2024 dependency release and its missing symbol-production pipeline for a Dev18 feature that was already unavailable and has no known user complaints.
  • It makes the unsupported behavior explicit before collection rather than producing an empty .diagsession.
  • Legacy support can still be reconsidered independently if usage data or customer demand justifies the upstream build, signing, and symbol archival work.

User impact

  • Dev18 Python profiling supports Python 3.12, 3.13, and 3.14.
  • Python 3.9, 3.10, and 3.11 users receive a clear warning before a profiling session starts.
  • Editing, running, and debugging older Python versions are unaffected.
  • The legacy profiler behavior in older Visual Studio releases is unaffected.

Manual validation

  • Built and deployed PTVS to the Dev18 Canary experimental hive.
  • Confirmed an older interpreter is rejected with the new warning and no empty session is created.
  • Confirmed Python 3.14 proceeds through profiling and reports user functions when the target defines and calls functions.
  • Confirmed the profiling VSIX contains the Python 3.12-3.14 etwtrace binaries and no etwtrace_legacy entries.

Remove the legacy etwtrace payload and reject unsupported interpreters before Diagnostics Hub starts a session.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 8b082fe2-2f94-4c5d-82a7-ea7b5a3284ef
@StellaHuang95
StellaHuang95 requested a review from a team as a code owner July 30, 2026 17:46
Copilot AI review requested due to automatic review settings July 30, 2026 17:46
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
There may be pipelines that require an authorized user to comment /azp run to run.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR narrows Dev18 Python profiling support to Python 3.12–3.14 to avoid shipping an etwtrace legacy payload whose native binaries fail Visual Studio insertion symbol policy, and to make unsupported interpreter scenarios fail early with clear messaging.

Changes:

  • Removes etwtrace 0.1b8 restore + etwtrace_legacy VSIX payload and related bootstrap compatibility logic.
  • Adds a pre-launch interpreter version probe in the profiling command service, showing actionable localized messages for unreadable/unsupported interpreters.
  • Updates the Python bootstrap (diaghub_profile.py) and build restore script to enforce/align the supported version range (3.12–3.14).
Show a summary per file
File Description
Python/Product/Profiling/Strings.resx Adds localized strings for interpreter-version-unavailable and unsupported-version messaging.
Python/Product/Profiling/Strings.Designer.cs Updates generated resource accessors for the new strings.
Python/Product/Profiling/Profiling/PythonProfilerCommandService.cs Probes interpreter version before returning Diagnostics Hub launch args; blocks unsupported/unreadable interpreters.
Python/Product/Profiling/Profiling.csproj Stops packaging etwtrace_legacy content into the profiling VSIX.
Python/Product/Profiling/diaghub_profile.py Removes legacy collector path and restricts runtime support to Python 3.12–3.14.
Build/PreBuild.ps1 Removes legacy etwtrace restore and installs only the supported etwtrace payload.

Review details

Files not reviewed (1)
  • Python/Product/Profiling/Strings.Designer.cs: Generated file
  • Files reviewed: 5/6 changed files
  • Comments generated: 1
  • Review effort level: Low

Comment thread Python/Product/Profiling/Profiling/PythonProfilerCommandService.cs
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings July 30, 2026 18:25
@StellaHuang95

Copy link
Copy Markdown
Contributor Author

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 1 pipeline(s).

@sonarqubecloud

Copy link
Copy Markdown

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review details

Files not reviewed (1)
  • Python/Product/Profiling/Strings.Designer.cs: Generated file
Comments suppressed due to low confidence (1)

Python/Product/Profiling/diaghub_profile.py:16

  • Changing the supported range to 3.12–3.14 will break the existing bootstrap tests: Python/Tests/ProfilingTests/ProfilingTests.cs currently prefers PythonPaths.Python39_x64/Python39 and diaghub_profile_tests.py::test_supported_versions asserts that (3,9) is supported. With _is_supported_version now requiring >= 3.12, these tests will start failing unless they’re updated to use 3.12+ and adjust the assertions.
def _is_supported_version(version):
    return (3, 12) <= tuple(version[:2]) <= (3, 14)
  • Files reviewed: 5/6 changed files
  • Comments generated: 0 new
  • Review effort level: Low

if not _is_supported_version(sys.version_info):
print(
"Visual Studio Python profiling supports Python 3.9 through 3.14.",
"Visual Studio Python profiling supports Python 3.12 through 3.14.",

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should be a loc string

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Its printed message is a fallback diagnostic. The normal user-facing unsupported-version message does come from PTVS before the session starts and uses localized Strings.resx.

@bschnurr bschnurr left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just the loc string

@StellaHuang95
StellaHuang95 merged commit 7f435c0 into microsoft:main Jul 30, 2026
8 checks passed
@StellaHuang95
StellaHuang95 deleted the drop-python39-311-profiling branch July 30, 2026 19:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants