Conversation
…indows - CPU: Use GetSystemTimes P/Invoke (kernel32.dll) instead of Get-CimInstance Win32_Processor - Memory: Use GlobalMemoryStatusEx P/Invoke (kernel32.dll) instead of Get-CimInstance Win32_OperatingSystem - DCP processes: Use Process.GetProcesses() filtered by name instead of PowerShell Get-Process - Top processes: Use Process.GetProcesses() sorted by CPU instead of PowerShell Get-Process - Disk: Use DriveInfo.GetDrives() instead of PowerShell Get-PSDrive - Share single Process.GetProcesses() call per cycle between DCP and Top metrics - Fix FILETIME.ToLong() to cast dwLowDateTime to long before bitwise OR (prevents overflow) - Apply consistent Math.Round to CPU% in GetTopProcesses to match GetDcpProcesses behavior Agent-Logs-Url: https://github.com/microsoft/aspire/sessions/980b8145-b029-436f-938b-b3f6da2078c7 Co-authored-by: radical <1472+radical@users.noreply.github.com>
Copilot
AI
changed the title
[WIP] Replace PowerShell process spawns with .NET APIs on Windows
Heartbeat.cs: Replace PowerShell process spawns with .NET APIs on Windows
Apr 4, 2026
Contributor
|
🚀 Dogfood this PR with:
curl -fsSL https://raw.githubusercontent.com/microsoft/aspire/main/eng/scripts/get-aspire-cli-pr.sh | bash -s -- 15888Or
iex "& { $(irm https://raw.githubusercontent.com/microsoft/aspire/main/eng/scripts/get-aspire-cli-pr.ps1) } 15888" |
10 tasks
Contributor
There was a problem hiding this comment.
Pull request overview
This PR optimizes the CI heartbeat diagnostics script on Windows by removing repeated PowerShell spawns and replacing them with zero-spawn .NET and Win32 API equivalents, reducing CPU/memory overhead on constrained windows-latest runners.
Changes:
- Replaced Windows CPU and memory metric collection with
GetSystemTimesandGlobalMemoryStatusExP/Invokes. - Reworked Windows “DCP processes” and “Top processes” to use a shared
Process.GetProcesses()snapshot per cycle (with explicit disposal). - Replaced Windows disk usage collection with
DriveInfo.GetDrives().
- Wrap ProcessName/Id reads inside try/catch in DCP process collection so a single exited process doesn't abort the entire cycle - Return nullable tuple in Top processes LINQ, filter nulls afterward, so ProcessName/Id are never read outside the guarded block - Remove unused prevCpu (TimeSpan) and prevDateTime (DateTime) params from GetCpuUsage and their caller-side variables Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
danegsta
approved these changes
Apr 6, 2026
radical
added a commit
that referenced
this pull request
Apr 6, 2026
…lelization disable - Cherry-pick Heartbeat.cs from PR #15888: replaces all 5 Windows PowerShell process spawns with .NET P/Invoke and BCL APIs (GetSystemTimes, GlobalMemoryStatusEx, Process.GetProcesses, DriveInfo.GetDrives) - Remove DisableTestParallelization from run-tests.yml build steps - Remove tests/Directory.Build.targets xunit.runner.json swap for DisableTestParallelization - Remove tests/github-actions/xunit.runner.json - Keep: VBCSCompiler shutdown, UseSharedCompilation=false, 60s heartbeat interval Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Contributor
|
🎬 CLI E2E Test Recordings — 56 recordings uploaded (commit View recordings
📹 Recordings uploaded automatically from CI run #24048287050 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
On Windows CI runners, the heartbeat monitor spawned 5 separate
powershell.exeprocesses per cycle — each loading the full PS runtime (~100MB, high CPU on init) — contributing to runner hangs on 2-corewindows-latestagents.Changes
All 5 Windows metric collection paths now use zero-spawn .NET equivalents:
Get-CimInstance Win32_ProcessorGetSystemTimesP/Invoke — idle/kernel/user time deltas (same approach as Linux/proc/stat)Get-CimInstance Win32_OperatingSystemGlobalMemoryStatusExP/Invoke — single syscallGet-Process -Name 'dcp*'Process.GetProcesses()filtered by name prefixGet-Process | Sort-Object CPUProcess.GetProcesses()call, sorted by CPU%Get-PSDrive -PSProvider FileSystemDriveInfo.GetDrives()Key optimizations:
Process.GetProcesses()is called once per cycle and shared between DCP and Top metrics, with process handles disposed after both reads complete.DllImportis used overLibraryImport(the script's auto-generated project doesn't haveAllowUnsafeBlocks); SYSLIB1054 suppressed via#pragma warning disable.FILETIME.ToLong()explicitly casts both fields tolongbefore bitwise OR to prevent sign-extension overflow.Checklist