Windows下快速运行程序的峰值内存占用测量方法问询
在Windows PowerShell中测量短耗时程序的峰值内存占用
需求背景
- 需要测量运行时间极短(<1秒)的Windows程序的峰值内存占用,资源监视器无法捕捉该数据
- 要对比同一份代码经cl、clang、gcc(Windows下)编译后的内存使用表现
- 希望找到类似Linux下
/usr/bin/time -v ./test的工具,能直接返回Maximum resident set size这类指标
已尝试方案及问题
我试过用两个PowerShell脚本包装目标程序,但无法正确获取内存数据:
test.ps1(包装目标程序)
# 设置应用程序路径 $applicationPath = ".\test.exe" # 设置延迟时间(秒) $delayInSeconds = 10 # 等待指定延迟,方便手动设置监控 Start-Sleep -Seconds $delayInSeconds # 启动目标程序 Start-Process -FilePath $applicationPath -PassThru # 再次等待,保留测量窗口 Start-Sleep -Seconds $delayInSeconds
bench.ps1(监控脚本)
Write-Host "启动基准测试" # 启动test.ps1子进程并获取PID $processId = Start-Process -FilePath "powershell.exe" -ArgumentList "-NoProfile -ExecutionPolicy Bypass -File .\test.ps1" -PassThru $id = $processId.id Write-Host "进程ID: $id" # 设置等待时间 $delayInSeconds = 15 Start-Sleep -Seconds $delayInSeconds # 读取峰值内存(工作集) $peakMemoryUsage = (Get-Process -Id $id).PeakWorkingSet64 / 1MB # 输出结果 Write-Host "进程ID: $processId" Write-Host "峰值内存占用: ${peakMemoryUsage} MB"
遇到的问题
无论修改test.exe中的内存分配量(比如添加无优化的大内存分配代码:std::vector<std::string> v(10000000,"Very long string to allocate at least something"); std::cout << v.back() << '\n';),测量出的内存值始终不变。推测是因为Start-Process会在独立进程中启动test.exe,导致监控的是powershell子进程而非目标程序的内存。
另外,也考虑过在test.exe中添加暂停逻辑,但希望找到无需修改目标程序的解决方案。
可行解决方案
方案1:PowerShell直接运行并监控(无嵌套脚本)
直接在脚本中启动目标程序并等待其退出,同时跟踪进程的峰值内存,避免嵌套进程导致的监控对象错误:
$targetExe = ".\test.exe" # 启动进程并保留进程对象 $proc = Start-Process -FilePath $targetExe -NoNewWindow -PassThru # 等待进程完全退出 Wait-Process -Id $proc.Id # 获取峰值内存并转换为MB $peakMemMB = $proc.PeakWorkingSet64 / 1MB Write-Host "目标程序: $targetExe" Write-Host "峰值内存占用: $peakMemMB MB"
方案2:使用Windows原生工具timeit.exe
Windows SDK自带的timeit.exe可以直接测量程序的运行时间和内存使用,用法类似Linux的time命令,输出包含Peak Working Set(峰值工作集)指标:
timeit.exe .\test.exe
如果找不到该工具,可通过安装Windows SDK获取,或从已安装的VS目录中查找(通常路径类似C:\Program Files (x86)\Windows Kits\10\bin\<版本>\x64\timeit.exe)。
方案3:性能计数器实时监控
通过Get-Counter实时跟踪进程内存,确保捕捉到短耗时程序的峰值:
$targetExe = ".\test.exe" # 启动进程 $proc = Start-Process -FilePath $targetExe -NoNewWindow -PassThru # 定义跟踪工作集的性能计数器 $counter = Get-Counter "\Process($($proc.ProcessName))\Working Set" $peakMem = 0 # 循环监控直到进程退出 while (!$proc.HasExited) { $current = ($counter.NextCounter().CounterSamples | Select-Object -ExpandProperty CookedValue) if ($current -gt $peakMem) { $peakMem = $current } Start-Sleep -Milliseconds 10 } # 最后再获取一次,确保不遗漏退出前的最大值 $finalPeak = ($counter.NextCounter().CounterSamples | Select-Object -ExpandProperty CookedValue) if ($finalPeak -gt $peakMem) { $peakMem = $finalPeak } $peakMemMB = $peakMem / 1MB Write-Host "峰值内存占用: $peakMemMB MB"
方案4:手动暂停验证(适合临时测试)
用Sysinternals的pssuspend工具临时暂停程序,方便手动在资源监视器中查看:
- 用包装脚本启动
test.exe前先等待几秒 - 等待期间执行
pssuspend test.exe暂停目标进程 - 查看内存数据后,执行
pssuspend -r test.exe恢复进程
此方法适合手动验证,自动化测试推荐前三种方案。
内容的提问来源于stack exchange,提问作者Oersted
相关产品推荐
相关产品推荐

