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