فهرست منبع

dockerversion: DockerUserAgent(): use sync.Once to construct User-Agent

The User-Agent includes the kernel version, which involves making a syscall
(and parsing the results) on Linux, and reading (plus parsing) the registry
on Windows. These operations are relatively costly, and we should not perform
those on every request that uses the User-Agent.

This patch adds a sync.Once so that we only perform these actions once for
the lifetime of the daemon's process.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
Sebastiaan van Stijn 2 سال پیش
والد
کامیت
66dfc0169f
1فایلهای تغییر یافته به همراه36 افزوده شده و 15 حذف شده
  1. 36 15
      dockerversion/useragent.go

+ 36 - 15
dockerversion/useragent.go

@@ -4,6 +4,7 @@ import (
 	"context"
 	"fmt"
 	"runtime"
+	"sync"
 
 	"github.com/docker/docker/pkg/parsers/kernel"
 	"github.com/docker/docker/pkg/useragent"
@@ -17,23 +18,43 @@ type UAStringKey struct{}
 //
 //	[docker client's UA] UpstreamClient([upstream client's UA])
 func DockerUserAgent(ctx context.Context) string {
-	httpVersion := make([]useragent.VersionInfo, 0, 6)
-	httpVersion = append(httpVersion, useragent.VersionInfo{Name: "docker", Version: Version})
-	httpVersion = append(httpVersion, useragent.VersionInfo{Name: "go", Version: runtime.Version()})
-	httpVersion = append(httpVersion, useragent.VersionInfo{Name: "git-commit", Version: GitCommit})
-	if kernelVersion, err := kernel.GetKernelVersion(); err == nil {
-		httpVersion = append(httpVersion, useragent.VersionInfo{Name: "kernel", Version: kernelVersion.String()})
+	daemonUA := getDaemonUserAgent()
+	if upstreamUA := getUserAgentFromContext(ctx); len(upstreamUA) > 0 {
+		return insertUpstreamUserAgent(upstreamUA, daemonUA)
 	}
-	httpVersion = append(httpVersion, useragent.VersionInfo{Name: "os", Version: runtime.GOOS})
-	httpVersion = append(httpVersion, useragent.VersionInfo{Name: "arch", Version: runtime.GOARCH})
+	return daemonUA
+}
 
-	dockerUA := useragent.AppendVersions("", httpVersion...)
-	upstreamUA := getUserAgentFromContext(ctx)
-	if len(upstreamUA) > 0 {
-		ret := insertUpstreamUserAgent(upstreamUA, dockerUA)
-		return ret
-	}
-	return dockerUA
+var (
+	daemonUAOnce sync.Once
+	daemonUA     string
+)
+
+// getUserAgentFromContext returns the user-agent to use for requests made by
+// the daemon.
+//
+// It includes;
+//
+// - the docker version
+// - go version
+// - git-commit
+// - kernel version
+// - os
+// - architecture
+func getDaemonUserAgent() string {
+	daemonUAOnce.Do(func() {
+		httpVersion := make([]useragent.VersionInfo, 0, 6)
+		httpVersion = append(httpVersion, useragent.VersionInfo{Name: "docker", Version: Version})
+		httpVersion = append(httpVersion, useragent.VersionInfo{Name: "go", Version: runtime.Version()})
+		httpVersion = append(httpVersion, useragent.VersionInfo{Name: "git-commit", Version: GitCommit})
+		if kernelVersion, err := kernel.GetKernelVersion(); err == nil {
+			httpVersion = append(httpVersion, useragent.VersionInfo{Name: "kernel", Version: kernelVersion.String()})
+		}
+		httpVersion = append(httpVersion, useragent.VersionInfo{Name: "os", Version: runtime.GOOS})
+		httpVersion = append(httpVersion, useragent.VersionInfo{Name: "arch", Version: runtime.GOARCH})
+		daemonUA = useragent.AppendVersions("", httpVersion...)
+	})
+	return daemonUA
 }
 
 // getUserAgentFromContext returns the previously saved user-agent context stored in ctx, if one exists