Open sudo-bmitch opened 2 years ago
Since this involves creating a tempdir, writing a binary, and executing that binary with an interpreter, ideally this would only be called once, and only if needed for a user query or running a step that needs an interpreter (like a RUN step in a Dockerfile for a platform other than the local platform).
An example of a call that doesn't make sense to me is:
That gets run just after a cached call to w.Platforms
. Either the Platforms
call shouldn't be cached or we don't need the immediate follow up call to WarnIfUnsupported
.
The line you linked only gets called once on daemon boot.
But there are other places where this gets called. It needs to be called every time you do workers ls
(equivalent buildx inspect
) and also when starting a build with unknown platform. This is because any changes to emulators should be picked up automatically without requiring buildkitd restart.
There seems to be something in your system as well as these invocations should be very fast as they are binaries with literally 2 assembly instructions.
The line you linked only gets called once on daemon boot.
Yup, but it did the same work on line 699 if it wasn't cached already (which it wouldn't be on startup), so it's 2x the calls.
There seems to be something in your system as well as these invocations should be very fast as they are binaries with literally 2 assembly instructions.
Entirely possible my system needs a replace/rebuild. I suspect it's more the fork/exec and qemu running the interpreter, than the assembly itself. An arm64 build takes 10x the time of the same amd64 build on my host, so there's definitely some qemu overhead on my system. The behavior also isn't consistent, sometimes it's only an extra second or two, other times it's hanging for 20 seconds, which I suspect has more to do with whether it's launching buildkitd or it was already running. But it's been noticeable since I tried out the 22.06 beta, and now with the 20.10.18 release.
What timings do you see when invoking this check command manually? Have you been able to reproduce long times or high CPU? Have you tried if using some other binfmt installation makes a difference?
Using the following check_test.go
:
package archutil
import "testing"
func BenchmarkSupportedPlatforms(b *testing.B) {
for n := 0; n < b.N; n++ {
pl := SupportedPlatforms(true)
if len(pl) < 5 {
b.Errorf("not enough platforms: %v", pl)
}
}
}
And running the test as root (for the chroot), I'm getting:
BenchmarkSupportedPlatforms-8 1438 16034324 ns/op
So it's not taking the over 0.5 sec for some platforms that I'm seeing during the docker builds. The standalone binaries are similarly fast.
$ time for file in bin/*; do echo $file; ./$file; done
bin/386
bin/amd64
bin/arm
bin/arm64
bin/mips64
bin/mips64le
bin/ppc64le
bin/riscv64
bin/s390x
real 0m0.098s
user 0m0.026s
sys 0m0.073s
I'll keep digging to see if I can track down the long startup times.
For a simple build of an image without any RUN steps, I'm seeing delays of 30 seconds, sometimes over a minute, before the build starts sending the context. During that time, I'm seeing multiple calls to the check command:
The above was seen when building:
With buildx:
With a docker-container driver:
Running on the 20.10.18 build of docker: