github.com/adityamillind98/moby@v23.0.0-rc.4+incompatible/daemon/top_windows.go (about) 1 package daemon // import "github.com/docker/docker/daemon" 2 3 import ( 4 "context" 5 "errors" 6 "fmt" 7 "time" 8 9 containertypes "github.com/docker/docker/api/types/container" 10 units "github.com/docker/go-units" 11 ) 12 13 // ContainerTop handles `docker top` client requests. 14 // 15 // Future considerations: 16 // - Windows users are far more familiar with CPU% total. 17 // Further, users on Windows rarely see user/kernel CPU stats split. 18 // The kernel returns everything in terms of 100ns. To obtain 19 // CPU%, we could do something like docker stats does which takes two 20 // samples, subtract the difference and do the maths. Unfortunately this 21 // would slow the stat call down and require two kernel calls. So instead, 22 // we do something similar to linux and display the CPU as combined HH:MM:SS.mmm. 23 // - Perhaps we could add an argument to display "raw" stats 24 // - "Memory" is an extremely overloaded term in Windows. Hence we do what 25 // task manager does and use the private working set as the memory counter. 26 // We could return more info for those who really understand how memory 27 // management works in Windows if we introduced a "raw" stats (above). 28 func (daemon *Daemon) ContainerTop(name string, psArgs string) (*containertypes.ContainerTopOKBody, error) { 29 // It's not at all an equivalent to linux 'ps' on Windows 30 if psArgs != "" { 31 return nil, errors.New("Windows does not support arguments to top") 32 } 33 34 container, err := daemon.GetContainer(name) 35 if err != nil { 36 return nil, err 37 } 38 39 if !container.IsRunning() { 40 return nil, errNotRunning(container.ID) 41 } 42 43 if container.IsRestarting() { 44 return nil, errContainerIsRestarting(container.ID) 45 } 46 47 s, err := daemon.containerd.Summary(context.Background(), container.ID) 48 if err != nil { 49 return nil, err 50 } 51 procList := &containertypes.ContainerTopOKBody{} 52 procList.Titles = []string{"Name", "PID", "CPU", "Private Working Set"} 53 54 for _, j := range s { 55 d := time.Duration((j.KernelTime_100Ns + j.UserTime_100Ns) * 100) // Combined time in nanoseconds 56 procList.Processes = append(procList.Processes, []string{ 57 j.ImageName, 58 fmt.Sprint(j.ProcessID), 59 fmt.Sprintf("%02d:%02d:%02d.%03d", int(d.Hours()), int(d.Minutes())%60, int(d.Seconds())%60, int(d.Nanoseconds()/1000000)%1000), 60 units.HumanSize(float64(j.MemoryWorkingSetPrivateBytes))}) 61 } 62 63 return procList, nil 64 }