summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--version/cmdname.go10
-rw-r--r--version/version_test.go20
2 files changed, 30 insertions, 0 deletions
diff --git a/version/cmdname.go b/version/cmdname.go
index 5a0b84875..8e6adb047 100644
--- a/version/cmdname.go
+++ b/version/cmdname.go
@@ -13,6 +13,7 @@ import (
"os"
"path"
"runtime"
+ "runtime/debug"
"strings"
)
@@ -20,6 +21,15 @@ import (
// using os.Executable. If os.Executable fails (it shouldn't), then
// "cmd" is returned.
func CmdName() string {
+ // On non-Windows, the modinfo embedded in the running binary is
+ // authoritative and avoids re-reading the executable from disk.
+ // Windows needs the executable-name-based GUI override in cmdName,
+ // so it still takes the slower path.
+ if runtime.GOOS != "windows" {
+ if info, ok := debug.ReadBuildInfo(); ok && info.Path != "" {
+ return path.Base(info.Path)
+ }
+ }
e, err := os.Executable()
if err != nil {
return "cmd"
diff --git a/version/version_test.go b/version/version_test.go
index 42bcf2163..01fcd47ec 100644
--- a/version/version_test.go
+++ b/version/version_test.go
@@ -6,6 +6,8 @@ package version_test
import (
"bytes"
"os"
+ "path"
+ "runtime/debug"
"testing"
ts "tailscale.com"
@@ -49,3 +51,21 @@ func TestShortAllocs(t *testing.T) {
t.Errorf("allocs = %v; want 0", allocs)
}
}
+
+func BenchmarkCmdName(b *testing.B) {
+ b.ReportAllocs()
+ for b.Loop() {
+ _ = version.CmdName()
+ }
+}
+
+func BenchmarkReadBuildInfo(b *testing.B) {
+ b.ReportAllocs()
+ for b.Loop() {
+ info, ok := debug.ReadBuildInfo()
+ if !ok {
+ b.Fatal("ReadBuildInfo failed")
+ }
+ _ = path.Base(info.Path)
+ }
+}