collectSnapshot fetches all process info, updates lastCPUSamples with fresh measurements, and computes CPU% using each pid's previous sample (if available).
(numCPU int)
| 244 | // collectSnapshot fetches all process info, updates lastCPUSamples with fresh measurements, |
| 245 | // and computes CPU% using each pid's previous sample (if available). |
| 246 | func (s *procCacheState) collectSnapshot(numCPU int) *wshrpc.ProcessListResponse { |
| 247 | ctx, cancel := context.WithTimeout(context.Background(), 8*time.Second) |
| 248 | defer cancel() |
| 249 | |
| 250 | procs, err := goproc.ProcessesWithContext(ctx) |
| 251 | if err != nil { |
| 252 | return nil |
| 253 | } |
| 254 | |
| 255 | if s.lastCPUSamples == nil { |
| 256 | s.lastCPUSamples = make(map[int32]cpuSample, len(procs)) |
| 257 | } |
| 258 | |
| 259 | snap, err := procinfo.MakeGlobalSnapshot() |
| 260 | if err != nil { |
| 261 | return nil |
| 262 | } |
| 263 | |
| 264 | hasCPU := s.lastCPUEpoch > 1 // first epoch has no previous sample to diff against |
| 265 | |
| 266 | type pidInfo struct { |
| 267 | pid int32 |
| 268 | info *procinfo.ProcInfo |
| 269 | } |
| 270 | rawInfos := make([]pidInfo, len(procs)) |
| 271 | for i, p := range procs { |
| 272 | pi, err := procinfo.GetProcInfo(ctx, snap, p.Pid) |
| 273 | if err != nil { |
| 274 | pi = nil |
| 275 | } |
| 276 | rawInfos[i] = pidInfo{pid: p.Pid, info: pi} |
| 277 | } |
| 278 | |
| 279 | // Sample CPU times and compute CPU% sequentially to keep epoch accounting simple. |
| 280 | cpuPcts := make(map[int32]float64, len(procs)) |
| 281 | sampleTime := time.Now() |
| 282 | for _, ri := range rawInfos { |
| 283 | if ri.info == nil { |
| 284 | continue |
| 285 | } |
| 286 | if ri.info.CpuUser < 0 || ri.info.CpuSys < 0 { |
| 287 | continue |
| 288 | } |
| 289 | curCPUSec := ri.info.CpuUser + ri.info.CpuSys |
| 290 | |
| 291 | if hasCPU { |
| 292 | if prev, ok := s.lastCPUSamples[ri.pid]; ok { |
| 293 | elapsed := sampleTime.Sub(prev.SampledAt).Seconds() |
| 294 | if elapsed > 0 { |
| 295 | cpuPcts[ri.pid] = computeCPUPct(prev.CPUSec, curCPUSec, elapsed) |
| 296 | } |
| 297 | } |
| 298 | } |
| 299 | |
| 300 | s.lastCPUSamples[ri.pid] = cpuSample{ |
| 301 | CPUSec: curCPUSec, |
| 302 | SampledAt: sampleTime, |
| 303 | Epoch: s.lastCPUEpoch, |
no test coverage detected