Skip to content
This repository has been archived by the owner on Oct 30, 2018. It is now read-only.

Reduce maximum memory usage via tempfiles #191

Merged
merged 3 commits into from
Dec 12, 2017

Conversation

ijc
Copy link
Collaborator

@ijc ijc commented Dec 6, 2017

Replacing a few uses of bytes.Buffer with temporary files or passing around io.Reader instead of a full buffer reduces the Maximum RSS (measured by time(1)) from 6.7G to 110M when building the kube-master.iso from https://github.com/linuxkit/kubernetes.

Motivation for looking into this was that in the https://github.com/linuxkit/kubernetes CI the image build process is occasionally being SIGKILL'd, since the CI containers are limited to 4G I hypothesised that the process was being OOM killed (I have not yet tested with these changes in place).

Since i have plenty of RAM no my test system the data, presumably, remains hot in the page cache so elapsed wallclock time is unaffected (it's a few seconds faster on a minute long build, so in the noise). On a memory (but not disk) constrained system it ought to complete slowly instead of getting killed.

Also adds -memprofile and -cpuprofile options to enable measurement, although I mostly ended up using `time(1) since the profiles show cumulative or overall allocations rather than max rss.

I'm not sure but with these changes it might be possible to mark some additional image formats as streaming.

Ian Campbell added 2 commits December 6, 2017 15:54
Following https://golang.org/pkg/runtime/pprof/. When attempting to build
images in https://github.com/linuxkit/kubernetes CI the process is mysteriously
being SIGKILL'd, which I think might be down to OOMing due to the resource
limits placed on the build container.

I haven't done so yet but I'm intending to use these options to investigate and
they seem potentially useful in any case, even if this turns out to be a
red-herring.

Signed-off-by: Ian Campbell <ijc@docker.com>
All of the `output*` functions took a `[]byte` and immediately wrapped it in a
`bytes.Buffer` to produce an `io.Reader`. Make them take an `io.Reader` instead
and satisfy this further up the call chain by directing `moby.Build` to output
to a temp file instead of another `bytes.Buffer`.

In my test case (building kube master image) this reduces Maximum RSS (as
measured by time(1)) from 6.7G to 2.8G and overall allocations from 9.7G to
5.3G. When building a tar (output to /dev/null) the Maximum RSS fell slightly
from 2.2G to 2.1G. Overall allocations remained stable at around 5.3G.

Signed-off-by: Ian Campbell <ijc@docker.com>
Rather than queueing up into a `bytes.Buffer`.

In my test case (building kube master image) this reduces Maximum RSS (as
measured by time(1)) compared with the previous patch from 2.8G to 110M. The
tar output case goes from 2.1G to 110M also. Overall allocations are ~715M in
both cases.

Signed-off-by: Ian Campbell <ijc@docker.com>
@ijc ijc force-pushed the reduce-memory-via-tempfiles branch from c3497b9 to 3045a80 Compare December 6, 2017 16:41
@ijc
Copy link
Collaborator Author

ijc commented Dec 7, 2017

FWIW the only remaining bytes.Buffer and source of the largest overhead now is the ones used in the kernelFilter, which I suspected account for a fair chunk of the new 110M maximum RSS, although looking at one kernel image the kernel.tar which I expected to be 80-100M or more is only 27M, so the max overhead from kernelFilter is probably not too bad right now. It could be made to use a temp file as well, but it doesn't seem worth it for now.

@justincormack justincormack merged commit ebd7228 into moby:master Dec 12, 2017
@ijc ijc deleted the reduce-memory-via-tempfiles branch December 13, 2017 10:10
ijc pushed a commit to ijc/moby-tool that referenced this pull request Dec 13, 2017
This was introduced by moby#191 but somehow did not trigger either for me in local
testing or in CI.

It did trigger in initial CI of linuxkit/linuxkit#2811
which can be seen at https://linuxkit.datakit.ci/linuxkit/linuxkit/pr/2811?history=1637690296123e9a15307b3a41b290da6e27e7cc
The error is:

    Failed to docker rm container «...»: «...»: aufs: unmount error after retries: «...»: device or resource busy

No doubt because we were still holding an open fd while trying to remove the
container.

Unclear why this didn't repro for me (docker 17.11.0-ce with overlay2) or
whatever CI uses.

Signed-off-by: Ian Campbell <ijc@docker.com>
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants