func trackCPUUsage() { handle, err := syscall.GetCurrentProcess() if err != nil { l.Warnln("Cannot track CPU usage:", err) return } var ctime, etime, ktime, utime syscall.Filetime err = syscall.GetProcessTimes(handle, &ctime, &etime, &ktime, &utime) if err != nil { l.Warnln("Cannot track CPU usage:", err) return } prevTime := ctime.Nanoseconds() prevUsage := ktime.Nanoseconds() + utime.Nanoseconds() // Always overflows for _ = range time.NewTicker(time.Second).C { err := syscall.GetProcessTimes(handle, &ctime, &etime, &ktime, &utime) if err != nil { continue } curTime := time.Now().UnixNano() timeDiff := curTime - prevTime curUsage := ktime.Nanoseconds() + utime.Nanoseconds() usageDiff := curUsage - prevUsage cpuUsageLock.Lock() copy(cpuUsagePercent[1:], cpuUsagePercent[0:]) cpuUsagePercent[0] = 100 * float64(usageDiff) / float64(timeDiff) cpuUsageLock.Unlock() prevTime = curTime prevUsage = curUsage } }
func (p *Process) wait() (ps *ProcessState, err error) { handle := atomic.LoadUintptr(&p.handle) s, e := syscall.WaitForSingleObject(syscall.Handle(handle), syscall.INFINITE) switch s { case syscall.WAIT_OBJECT_0: break case syscall.WAIT_FAILED: return nil, NewSyscallError("WaitForSingleObject", e) default: return nil, errors.New("os: unexpected result from WaitForSingleObject") } var ec uint32 e = syscall.GetExitCodeProcess(syscall.Handle(handle), &ec) if e != nil { return nil, NewSyscallError("GetExitCodeProcess", e) } var u syscall.Rusage e = syscall.GetProcessTimes(syscall.Handle(handle), &u.CreationTime, &u.ExitTime, &u.KernelTime, &u.UserTime) if e != nil { return nil, NewSyscallError("GetProcessTimes", e) } p.setDone() // NOTE(brainman): It seems that sometimes process is not dead // when WaitForSingleObject returns. But we do not know any // other way to wait for it. Sleeping for a while seems to do // the trick sometimes. So we will sleep and smell the roses. defer time.Sleep(5 * time.Millisecond) defer p.Release() return &ProcessState{p.Pid, syscall.WaitStatus{ExitCode: ec}, &u}, nil }
func (self *ProcTime) Get(pid int) error { handle, err := syscall.OpenProcess(syscall.PROCESS_QUERY_INFORMATION, false, uint32(pid)) defer syscall.CloseHandle(handle) if err != nil { return fmt.Errorf("OpenProcess fails with %v", err) } var CPU syscall.Rusage if err := syscall.GetProcessTimes(handle, &CPU.CreationTime, &CPU.ExitTime, &CPU.KernelTime, &CPU.UserTime); err != nil { return fmt.Errorf("GetProcessTimes fails with %v", err) } // convert to millis self.StartTime = uint64(FiletimeToDuration(&CPU.CreationTime).Nanoseconds() / 1e6) self.User = uint64(FiletimeToDuration(&CPU.UserTime).Nanoseconds() / 1e6) self.Sys = uint64(FiletimeToDuration(&CPU.KernelTime).Nanoseconds() / 1e6) self.Total = self.User + self.Sys return nil }
func (process *jobProcess) Wait() (int, error) { s, e := syscall.WaitForSingleObject(syscall.Handle(process.processHandle), syscall.INFINITE) switch s { case syscall.WAIT_OBJECT_0: break case syscall.WAIT_FAILED: return -1, os.NewSyscallError("WaitForSingleObject", e) default: return -1, errors.New("os: unexpected result from WaitForSingleObject") } var ec uint32 e = syscall.GetExitCodeProcess(syscall.Handle(process.processHandle), &ec) if e != nil { return -1, os.NewSyscallError("GetExitCodeProcess", e) } var u syscall.Rusage e = syscall.GetProcessTimes(syscall.Handle(process.processHandle), &u.CreationTime, &u.ExitTime, &u.KernelTime, &u.UserTime) if e != nil { return -1, os.NewSyscallError("GetProcessTimes", e) } // NOTE(brainman): It seems that sometimes process is not dead // when WaitForSingleObject returns. But we do not know any // other way to wait for it. Sleeping for a while seems to do // the trick sometimes. So we will sleep and smell the roses. defer time.Sleep(5 * time.Millisecond) defer syscall.CloseHandle(syscall.Handle(process.processHandle)) return int(ec), nil }
func UpdateProcessTimes(pdata *PlatformData, result *SubprocessResult, finished bool) error { var creation, end, user, kernel syscall.Filetime err := syscall.GetProcessTimes(pdata.hProcess, &creation, &end, &kernel, &user) if err != nil { return err } if !finished { syscall.GetSystemTimeAsFileTime(&end) } result.WallTime = filetimeToDuration(&end) - filetimeToDuration(&creation) var jinfo *win32.JobObjectBasicAccountingInformation if pdata.hJob != syscall.InvalidHandle { jinfo, err = win32.GetJobObjectBasicAccountingInformation(pdata.hJob) if err != nil { log.Error(err) } } if jinfo != nil { result.UserTime = ns100toDuration(jinfo.TotalUserTime) result.KernelTime = ns100toDuration(jinfo.TotalKernelTime) result.TotalProcesses = uint64(jinfo.TotalProcesses) } else { result.UserTime = filetimeToDuration(&user) result.KernelTime = filetimeToDuration(&kernel) } return nil }
func InitSysStats(N uint64) (ss sysStats) { if err := syscall.GetProcessTimes(currentProcess, &ss.CPU.CreationTime, &ss.CPU.ExitTime, &ss.CPU.KernelTime, &ss.CPU.UserTime); err != nil { log.Printf("GetProcessTimes failed: %v", err) return } ss.N = N return ss }
func RunAndCollectSysStats(cmd *exec.Cmd, res *Result, N uint64, prefix string) (string, error) { initJobOnce.Do(initJob) childMu.Lock() children := childProcesses childProcesses = []syscall.Handle{} childMu.Unlock() for _, proc := range children { syscall.CloseHandle(proc) } var out bytes.Buffer cmd.Stdout = &out cmd.Stderr = &out t0 := time.Now() if err := cmd.Run(); err != nil { return out.String(), err } t1 := time.Now() res.RunTime = uint64(t1.Sub(t0)) / N res.Metrics[prefix+"time"] = res.RunTime childMu.Lock() children = childProcesses childProcesses = []syscall.Handle{} childMu.Unlock() if len(children) == 0 { log.Printf("sysStats.Collect: no child processes?") return out.String(), nil } defer func() { for _, proc := range children { syscall.CloseHandle(proc) } }() cputime := uint64(0) rss := uint64(0) for _, proc := range children { var Mem PROCESS_MEMORY_COUNTERS if err := getProcessMemoryInfo(proc, &Mem); err != nil { log.Printf("GetProcessMemoryInfo failed: %v", err) return out.String(), nil } var CPU syscall.Rusage if err := syscall.GetProcessTimes(proc, &CPU.CreationTime, &CPU.ExitTime, &CPU.KernelTime, &CPU.UserTime); err != nil { log.Printf("GetProcessTimes failed: %v", err) return out.String(), nil } cputime += getCPUTime(CPU) / N rss += uint64(Mem.PeakWorkingSetSize) } res.Metrics[prefix+"cputime"] = cputime res.Metrics[prefix+"rss"] = rss return out.String(), nil }
func GetProcessTimes(proc *os.Process) (kernel, user time.Duration, err error) { handle := GetProcessHandle(proc) //fmt.Println(">>>>>Handle:", handle) var _create syscall.Filetime var _exit syscall.Filetime var _kernel syscall.Filetime var _user syscall.Filetime err = syscall.GetProcessTimes(syscall.Handle(handle), &_create, &_exit, &_kernel, &_user) kernel, user = FiletimeToDuration(&_kernel), FiletimeToDuration(&_user) //fmt.Println(">>>>>t:", err, kernel, user) return }
func getRusage(pid int32) (*syscall.Rusage, error) { var CPU syscall.Rusage c, err := syscall.OpenProcess(syscall.PROCESS_QUERY_INFORMATION, false, uint32(pid)) if err != nil { return nil, err } defer syscall.CloseHandle(c) if err := syscall.GetProcessTimes(c, &CPU.CreationTime, &CPU.ExitTime, &CPU.KernelTime, &CPU.UserTime); err != nil { return nil, err } return &CPU, nil }
func (p Process) usage() (*TimeUsage, error) { var u syscall.Rusage err := syscall.GetProcessTimes(syscall.Handle(p.handle), &u.CreationTime, &u.ExitTime, &u.KernelTime, &u.UserTime) if err != nil { return nil, os.NewSyscallError("GetProcessTimes", err) } return &TimeUsage{ CreationTime: time.Unix(0, u.CreationTime.Nanoseconds()), ExitTime: time.Unix(0, u.ExitTime.Nanoseconds()), KernelTime: toDuration(u.KernelTime), UserTime: toDuration(u.UserTime), }, nil }
func (ss sysStats) Collect(res *Result) { if ss.N == 0 { return } var Mem PROCESS_MEMORY_COUNTERS if err := getProcessMemoryInfo(currentProcess, &Mem); err != nil { log.Printf("GetProcessMemoryInfo failed: %v", err) return } var CPU syscall.Rusage if err := syscall.GetProcessTimes(currentProcess, &CPU.CreationTime, &CPU.ExitTime, &CPU.KernelTime, &CPU.UserTime); err != nil { log.Printf("GetProcessTimes failed: %v", err) return } res.Metrics["cputime"] = (getCPUTime(CPU) - getCPUTime(ss.CPU)) / ss.N res.Metrics["rss"] = uint64(Mem.PeakWorkingSetSize) }
// GetUsage gathers process times. func GetUsage() (Usage, error) { var creationTime syscall.Filetime var exitTime syscall.Filetime var kernelTime syscall.Filetime var userTime syscall.Filetime handle, err := syscall.GetCurrentProcess() if err != nil { return Usage{}, err } err = syscall.GetProcessTimes(handle, &creationTime, &exitTime, &kernelTime, &userTime) if err != nil { return Usage{}, err } return Usage{ System: filetimeToDuration(&kernelTime), User: filetimeToDuration(&userTime), }, nil }
func (self *ProcTime) Get(pid int) error { handle, err := syscall.OpenProcess(processQueryLimitedInfoAccess, false, uint32(pid)) if err != nil { return errors.Wrapf(err, "OpenProcess failed for pid=%v", pid) } defer syscall.CloseHandle(handle) var CPU syscall.Rusage if err := syscall.GetProcessTimes(handle, &CPU.CreationTime, &CPU.ExitTime, &CPU.KernelTime, &CPU.UserTime); err != nil { return errors.Wrapf(err, "GetProcessTimes failed for pid=%v", pid) } // Windows epoch times are expressed as time elapsed since midnight on // January 1, 1601 at Greenwich, England. This converts the Filetime to // unix epoch in milliseconds. self.StartTime = uint64(CPU.CreationTime.Nanoseconds() / 1e6) // Convert to millis. self.User = uint64(windows.FiletimeToDuration(&CPU.UserTime).Nanoseconds() / 1e6) self.Sys = uint64(windows.FiletimeToDuration(&CPU.KernelTime).Nanoseconds() / 1e6) self.Total = self.User + self.Sys return nil }