如何定期测量Go与Python程序的CPU(核心数)和内存使用量?
针对Go/Python程序的定时性能采集方案
以下是几种可行的解决办法,覆盖系统级无侵入采集、程序内埋点采集和专业工具三种场景:
一、系统级无侵入脚本采集(无需修改程序)
适用于不想改动目标代码的场景,利用系统工具定时获取进程的CPU和内存数据。
Linux/macOS 环境
- 先获取目标进程的PID:通过
pgrep <程序名称>或ps aux | grep <程序名称>过滤得到Go和Python程序的PID。 - 运行以下bash脚本,指定PID、采集时长和间隔:
#!/bin/bash PID_GO=<Go程序PID> PID_PY=<Python程序PID> DURATION=60 # 采集总时长(秒) INTERVAL=0.1 # 采集间隔(秒) COUNT=$((DURATION / INTERVAL)) echo "时间戳,Go_CPU(%),Go_内存(MB),Python_CPU(%),Python_内存(MB)" for ((i=0; i<COUNT; i++)) do TIMESTAMP=$(date +%s.%N) # 采集Go程序数据 GO_STATS=$(ps -p $PID_GO -o %cpu,rss | tail -n1) GO_CPU=$(echo $GO_STATS | awk '{print $1}') GO_MEM=$(echo $GO_STATS | awk '{print $2/1024}') # 采集Python程序数据 PY_STATS=$(ps -p $PID_PY -o %cpu,rss | tail -n1) PY_CPU=$(echo $PY_STATS | awk '{print $1}') PY_MEM=$(echo $PY_STATS | awk '{print $2/1024}') # 输出CSV格式数据,方便后续分析 echo "$TIMESTAMP,$GO_CPU,$GO_MEM,$PY_CPU,$PY_MEM" sleep $INTERVAL done
脚本说明:%cpu返回进程的CPU占用百分比,rss是进程常驻内存大小(单位KB),转换为MB便于阅读。如果需要更高精度的CPU统计,可替换为top -b -n1 -p $PID_GO,但ps更轻量,适合0.1秒级的高频采集。
Windows 环境
用PowerShell脚本结合WMI获取进程数据:
$pidGo = <Go程序PID> $pidPy = <Python程序PID> $duration = 60 # 采集时长(秒) $interval = 0.1 # 采集间隔(秒) $count = [math]::Floor($duration / $interval) Write-Host "时间戳,Go_CPU(%),Go_内存(MB),Python_CPU(%),Python_内存(MB)" for ($i=0; $i -lt $count; $i++) { $timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss.fff" # 获取Go进程数据 $goProc = Get-WmiObject Win32_PerfFormattedData_PerfProc_Process -Filter "IDProcess = $pidGo" $goCpu = $goProc.PercentProcessorTime $goMem = [math]::Round($goProc.WorkingSetPrivate / 1MB, 2) # 获取Python进程数据 $pyProc = Get-WmiObject Win32_PerfFormattedData_PerfProc_Process -Filter "IDProcess = $pidPy" $pyCpu = $pyProc.PercentProcessorTime $pyMem = [math]::Round($pyProc.WorkingSetPrivate / 1MB, 2) # 输出数据 Write-Host "$timestamp,$goCpu,$goMem,$pyCpu,$pyMem" Start-Sleep -Seconds $interval }
二、程序内埋点采集(精度更高)
如果允许修改目标程序代码,直接在程序内部定时采集自身性能数据,精度更高,无需依赖外部工具。
Go 程序
使用gopsutil库简化采集逻辑(可通过go get安装):
package main import ( "fmt" "time" "github.com/shirou/gopsutil/v3/process" ) func main() { selfPid := int32(process.Pid) proc, err := process.NewProcess(selfPid) if err != nil { panic(err) } totalDuration := 60 * time.Second collectInterval := 100 * time.Millisecond endTime := time.Now().Add(totalDuration) fmt.Println("时间戳,CPU(%),内存(MB)") for time.Now().Before(endTime) { ts := time.Now().Format("2006-01-02 15:04:05.000") cpuPercent, _ := proc.CPUPercent() memInfo, _ := proc.MemoryInfo() memMB := float64(memInfo.RSS) / 1024 / 1024 fmt.Printf("%s,%.2f,%.2f\n", ts, cpuPercent, memMB) time.Sleep(collectInterval) } }
说明:CPUPercent()返回两次调用之间的CPU占比,首次调用会返回0,后续数据正常。若不想引入第三方库,可使用runtime.ReadMemStats()获取内存数据,但CPU占比需自行计算,复杂度较高。
Python 程序
使用psutil库(可通过pip install psutil安装):
import psutil import time def monitor_self(): self_proc = psutil.Process() total_duration = 60 # 采集总时长(秒) collect_interval = 0.1 # 采集间隔(秒) end_time = time.time() + total_duration print("时间戳,CPU(%),内存(MB)") while time.time() < end_time: ts = time.strftime("%Y-%m-%d %H:%M:%S.%f")[:-3] cpu_percent = self_proc.cpu_percent(interval=None) mem_info = self_proc.memory_info() mem_mb = mem_info.rss / 1024 / 1024 print(f"{ts},{cpu_percent:.2f},{mem_mb:.2f}") time.sleep(collect_interval) if __name__ == "__main__": monitor_self()
说明:cpu_percent(interval=None)返回上次调用后的CPU占比,首次调用值为0,后续数据正常。rss字段对应进程的常驻内存大小。
三、专业监控工具(适合长期/大规模测试)
如果需要可视化分析、告警等功能,可使用:
- Prometheus + Grafana:给Go/Python程序添加metrics暴露接口,用Prometheus定时采集数据,Grafana生成可视化报表。配置稍复杂,但适合长期性能监控场景。
- perf(Linux):可采集进程底层性能数据,包括CPU指令、内存访问等,适合深度性能调优,但不侧重定时统计类数据。
内容的提问来源于stack exchange,提问作者Johnney
相关产品推荐
相关产品推荐

