docker / for-linux

Docker Engine for Linux
https://docs.docker.com/engine/installation/
755 stars 85 forks source link

when doing nothing, still wakes up the system at ~80hz #382

Open jimdigriz opened 6 years ago

jimdigriz commented 6 years ago

Expected behavior

When docker has nothing to do, argubly even when it does as it should be only the applications in the containers eating CPU time, it should let the CPU drop into low power sleep mode. It currently wakes the machine at least 80 times a second preventing this so it toasts battery life.

Over five years ago the Linux world went tickless and it highlighted a lot of software was found to really be awful for power saving as they utilised idle polling loops typically 10->200hz. Over time, and a pile of bug reports later, the world seemed to rediscover event driven software design :)

Docker missed the memo.

Actual behavior

dockerd has a 50hz idle poll loop, docker-containerd has a 30hz idle poll loop.

For comparison, Firefox is 4hz, Chrome is 3hz, and XOrg is 10hz.

Steps to reproduce the behavior

Run powertop, notice that when there are no containers, you are not even using docker, it is waking your laptop up to do seemingly nothing at 50hz (on dockerd) and 30hz (on docker-containerd).

Run strace shows select() (probably in your main idle loop) with timeouts set to tv_nsec=20000, that always return just ETIMEOUT.

Output of dpkg -s docker-ce:

Package: docker-ce
Status: install ok installed
Priority: optional
Section: admin
Installed-Size: 192775
Maintainer: Docker <support@docker.com>
Architecture: amd64
Version: 18.06.0~ce~3-0~debian
Replaces: docker-engine
Depends: iptables, init-system-helpers (>= 1.18~), libc6 (>= 2.17), libdevmapper1.02.1 (>= 2:1.02.97), libltdl7 (>= 2.4.6), libseccomp2 (>= 2.3.0), libsystemd0
Recommends: aufs-tools, ca-certificates, cgroupfs-mount | cgroup-lite, git, pigz, xz-utils
Conflicts: docker (<< 1.5~), docker-ee, docker-engine, docker-engine-cs, docker.io, lxc-docker, lxc-docker-virtual-package
Conffiles:
 /etc/default/docker 82d6a44e99db1a3b74f7835e4f5e1b01
 /etc/init.d/docker e593c2ca26facbf89018d4c708738c97
 /etc/init/docker.conf 123f7e2b4078fa11b4eecc4c4f9bdc25
Description: Docker: the open-source application container engine
 Docker is an open source project to build, ship and run any application as a
 lightweight container
 .
 Docker containers are both hardware-agnostic and platform-agnostic. This means
 they can run anywhere, from your laptop to the largest cloud compute instance and
 everything in between - and they don't require you to use a particular
 language, framework or packaging system. That makes them great building blocks
 for deploying and scaling web apps, databases, and backend services without
 depending on a particular stack or provider.
Homepage: https://www.docker.com

Output of docker version:

Client:
 Version:           18.06.0-ce
 API version:       1.38
 Go version:        go1.10.3
 Git commit:        0ffa825
 Built:             Wed Jul 18 19:09:33 2018
 OS/Arch:           linux/amd64
 Experimental:      false

Server:
 Engine:
  Version:          18.06.0-ce
  API version:      1.38 (minimum version 1.12)
  Go version:       go1.10.3
  Git commit:       0ffa825
  Built:            Wed Jul 18 19:07:38 2018
  OS/Arch:          linux/amd64
  Experimental:     false

Output of docker info:

Containers: 0
 Running: 0
 Paused: 0
 Stopped: 0
Images: 20
Server Version: 18.06.0-ce
Storage Driver: overlay2
 Backing Filesystem: extfs
 Supports d_type: true
 Native Overlay Diff: true
Logging Driver: json-file
Cgroup Driver: cgroupfs
Plugins:
 Volume: local
 Network: bridge host macvlan null overlay
 Log: awslogs fluentd gcplogs gelf journald json-file logentries splunk syslog
Swarm: inactive
Runtimes: runc
Default Runtime: runc
Init Binary: docker-init
containerd version: d64c661f1d51c48782c9cec8fda7604785f93587
runc version: 69663f0bd4b60df09991c08812a60108003fa340
init version: fec3683
Security Options:
 apparmor
 seccomp
  Profile: default
Kernel Version: 4.16.0-rc7-mssp4
Operating System: Debian GNU/Linux 9 (stretch)
OSType: linux
Architecture: x86_64
CPUs: 4
Total Memory: 7.721GiB
Name: quatermain
ID: HOFX:F25X:AOFJ:GD6M:ZMIQ:R4TO:63AH:J66W:PXRA:5XQG:6PVY:Q2XW
Docker Root Dir: /var/lib/docker
Debug Mode (client): false
Debug Mode (server): false
Username: jimdigriz
Registry: https://index.docker.io/v1/
Labels:
Experimental: false
Insecure Registries:
 127.0.0.0/8
Live Restore Enabled: false

WARNING: No swap limit support
raxod502 commented 4 years ago

For my personal use, I have constructed a horrifying workaround that halts the Docker service and brings down its network interfaces when no containers are running. It likely breaks things, but I'll take that over sacrificing a good percentage of my laptop's battery life. Put this in the system crontab to run every minute:

pgrep -af '/docker($| )' ||                 \
    (docker ps -q | grep . ||                   \
         (systemctl stop docker &&              \
              ip -brief link show |             \
                  awk '{ print $1 }' |              \
                  grep -E '^(docker0|br-[0-9a-f]{12})$' |   \
                  xargs -INAME ip link set dev NAME down    \
         )                          \
    )

I have a docker script on my PATH that takes care of re-starting the service automatically when it's needed, as well as re-running with sudo unless on macOS:

#!/usr/bin/env bash

export PATH="${PATH/$(dirname "$0"):/}"

if [[ "$OSTYPE" != darwin* ]] && [[ "$EUID" != 0 ]]; then
    if command -v systemctl >/dev/null; then
        sudo systemctl start docker
    fi
    sudo docker "$@"
else
    docker "$@"
fi

Improvements welcome.