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
	}
}
Exemple #2
0
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
}
Exemple #3
0
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
}
Exemple #9
0
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
}
Exemple #10
0
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)
}
Exemple #12
0
// 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
}
Exemple #13
0
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
}