Skip to content

CRI: improve image pulling performance#6702

Merged
dmcgowan merged 1 commit intocontainerd:mainfrom
fuweid:RFC-enhance-pull-performance
Apr 6, 2022
Merged

CRI: improve image pulling performance#6702
dmcgowan merged 1 commit intocontainerd:mainfrom
fuweid:RFC-enhance-pull-performance

Conversation

@fuweid
Copy link
Copy Markdown
Member

@fuweid fuweid commented Mar 19, 2022

Background:

With current design, the content backend uses key-lock for long-lived
write transaction. If the content reference has been marked for write
transaction, the other requestes on the same reference will fail fast with
unavailable error. Since the metadata plugin is based on boltbd which
only supports single-writer, the content backend can't block or handle
the request too long. It requires the client to handle retry by itself,
like OpenWriter - backoff retry helper. But the maximum retry interval
can be up to 2 seconds. If there are several concurrent requestes fo the
same image, the waiters maybe wakeup at the same time and there is only
one waiter can continue. A lot of waiters will get into sleep and we will
take long time to finish all the pulling jobs and be worse if the image
has many more layers, which mentioned in issue #4937.

After fetching, containerd.Pull API allows several hanlers to commit
same ChainID snapshotter but only one can be done successfully. Since
unpack tar.gz is time-consuming job, it can impact the performance on
unpacking for same ChainID snapshotter in parallel.

For instance, the Request 2 doesn't need to prepare and commit, it
should just wait for Request 1 finish, which mentioned in pull
request #6318.

	Request 1	Request 2

	Prepare
	   |
	   |
	   |
	   |		Prepare
	Commit		   |
			   |
			   |
			   |
			Commit(failed on exist)

Both content backoff retry and unnecessary unpack impacts the performance.

Solution:

Introduced the duplicate suppression in fetch and unpack context. The
deplicate suppression uses key-mutex and single-waiter-notify to support
singleflight. The caller can use the duplicate suppression in different
PullImage handlers so that we can avoid unnecessary unpack and spin-lock
in OpenWriter.

Test Result:

Before enhancement:

➜  /tmp sudo bash testing.sh "localhost:5000/redis:latest" 20
crictl pull localhost:5000/redis:latest (x20) takes ...

real	1m6.172s
user	0m0.268s
sys	0m0.193s

docker pull localhost:5000/redis:latest (x20) takes ...

real	0m1.324s
user	0m0.441s
sys	0m0.316s

➜  /tmp sudo bash testing.sh "localhost:5000/golang:latest" 20
crictl pull localhost:5000/golang:latest (x20) takes ...

real	1m47.657s
user	0m0.284s
sys	0m0.224s

docker pull localhost:5000/golang:latest (x20) takes ...

real	0m6.381s
user	0m0.488s
sys	0m0.358s

With this enhancement:

➜  /tmp sudo bash testing.sh "localhost:5000/redis:latest" 20
crictl pull localhost:5000/redis:latest (x20) takes ...

real	0m1.140s
user	0m0.243s
sys	0m0.178s

docker pull localhost:5000/redis:latest (x20) takes ...

real	0m1.239s
user	0m0.463s
sys	0m0.275s

➜  /tmp sudo bash testing.sh "localhost:5000/golang:latest" 20
crictl pull localhost:5000/golang:latest (x20) takes ...

real	0m5.546s
user	0m0.217s
sys	0m0.219s

docker pull localhost:5000/golang:latest (x20) takes ...

real	0m6.090s
user	0m0.501s
sys	0m0.331s

Test Script:

localhost:5000/{redis|golang}:latest is equal to
docker.io/library/{redis|golang}:latest. The image is hold in local registry
service by docker run -d -p 5000:5000 --name registry registry:2.

image_name="${1}"
pull_times="${2:-10}"

cleanup() {
  ctr image rmi "${image_name}"
  ctr -n k8s.io image rmi "${image_name}"
  crictl rmi "${image_name}"
  docker rmi "${image_name}"
  sleep 2
}

crictl_testing() {
  for idx in $(seq 1 ${pull_times}); do
    crictl pull "${image_name}" > /dev/null 2>&1 &
  done
  wait
}

docker_testing() {
  for idx in $(seq 1 ${pull_times}); do
    docker pull "${image_name}" > /dev/null 2>&1 &
  done
  wait
}

cleanup > /dev/null 2>&1

echo 3 > /proc/sys/vm/drop_caches
sleep 3
echo "crictl pull $image_name (x${pull_times}) takes ..."
time crictl_testing
echo

echo 3 > /proc/sys/vm/drop_caches
sleep 3
echo "docker pull $image_name (x${pull_times}) takes ..."
time docker_testing

Fixes: #4937
Close: #4985
Close: #6318

Signed-off-by: Wei Fu fuweid89@gmail.com

@theopenlab-ci
Copy link
Copy Markdown

theopenlab-ci bot commented Mar 19, 2022

Build succeeded.

@fuweid fuweid force-pushed the RFC-enhance-pull-performance branch from bc264a8 to 83a30dc Compare March 19, 2022 07:52
@theopenlab-ci
Copy link
Copy Markdown

theopenlab-ci bot commented Mar 19, 2022

Build succeeded.

@fuweid
Copy link
Copy Markdown
Member Author

fuweid commented Mar 19, 2022

ping @dmcgowan @dcantah @mikebrow @cpuguy83 @kzys ~

@AkihiroSuda AkihiroSuda added area/cri Container Runtime Interface (CRI) kind/performance labels Mar 19, 2022
@fuweid fuweid force-pushed the RFC-enhance-pull-performance branch 3 times, most recently from affc373 to 47925ba Compare March 20, 2022 03:01
@theopenlab-ci
Copy link
Copy Markdown

theopenlab-ci bot commented Mar 20, 2022

Build succeeded.

@fuweid
Copy link
Copy Markdown
Member Author

fuweid commented Mar 20, 2022

@AkihiroSuda Updated. PTAL

@fuweid fuweid force-pushed the RFC-enhance-pull-performance branch from 47925ba to efb5dad Compare March 22, 2022 15:28
@theopenlab-ci
Copy link
Copy Markdown

theopenlab-ci bot commented Mar 23, 2022

Build succeeded.

@fuweid fuweid force-pushed the RFC-enhance-pull-performance branch from 07e8c86 to ad75b27 Compare March 24, 2022 23:18
@theopenlab-ci
Copy link
Copy Markdown

theopenlab-ci bot commented Apr 5, 2022

Build succeeded.

@fuweid
Copy link
Copy Markdown
Member Author

fuweid commented Apr 6, 2022

CI is green!

@dmcgowan dmcgowan added this to the 1.7 milestone Apr 6, 2022
@dmcgowan dmcgowan merged commit a5b0d3b into containerd:main Apr 6, 2022
@fuweid fuweid deleted the RFC-enhance-pull-performance branch April 6, 2022 04:31
dewjam added a commit to dewjam/containerd that referenced this pull request Apr 22, 2022
dewjam added a commit to dewjam/containerd that referenced this pull request Apr 22, 2022
Signed-off-by: Jim DeWaard <dewaard@amazon.com>
smira added a commit to smira/talos that referenced this pull request Apr 26, 2022
This includes a fix for image pull slowness from
containerd/containerd#6702.

Signed-off-by: Andrey Smirnov <andrey.smirnov@talos-systems.com>
smira added a commit to smira/talos that referenced this pull request Apr 26, 2022
This includes a fix for image pull slowness from
containerd/containerd#6702.

Signed-off-by: Andrey Smirnov <andrey.smirnov@talos-systems.com>
smira added a commit to smira/talos that referenced this pull request Apr 28, 2022
This includes a fix for image pull slowness from
containerd/containerd#6702.

Signed-off-by: Andrey Smirnov <andrey.smirnov@talos-systems.com>
(cherry picked from commit 1973095)
smira added a commit to smira/talos that referenced this pull request May 4, 2022
This includes a fix for image pull slowness from
containerd/containerd#6702.

Signed-off-by: Andrey Smirnov <andrey.smirnov@talos-systems.com>
(cherry picked from commit 1973095)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/cri Container Runtime Interface (CRI) kind/performance

Projects

Archived in project

Development

Successfully merging this pull request may close these issues.

Poor parallel image pulling performance when cold

9 participants