From 21ac11312f156526f55fb4e2b8220cc73fc87325 Mon Sep 17 00:00:00 2001 From: Alec Fong Date: Fri, 27 Feb 2026 17:32:54 -0800 Subject: [PATCH 1/2] perf(analytics): timeout GPU info collection at 100ms nvidia-smi and system_profiler can be slow. Wrap getGPUInfo in a goroutine with a 100ms deadline so it never blocks CLI responsiveness. --- pkg/analytics/posthog.go | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/pkg/analytics/posthog.go b/pkg/analytics/posthog.go index 9d7b50cd..5743035c 100644 --- a/pkg/analytics/posthog.go +++ b/pkg/analytics/posthog.go @@ -319,9 +319,24 @@ func getTimezone() string { } func getGPUInfo() string { + type result struct { + out string + } + ch := make(chan result, 1) + go func() { + ch <- result{out: getGPUInfoSync()} + }() + select { + case r := <-ch: + return r.out + case <-time.After(100 * time.Millisecond): + return "" + } +} + +func getGPUInfoSync() string { out, err := exec.Command("nvidia-smi", "--query-gpu=name,memory.total,driver_version,count", "--format=csv,noheader,nounits").Output() // #nosec G204 if err != nil { - // nvidia-smi not available or no NVIDIA GPU if runtime.GOOS == "darwin" { return getAppleGPUInfo() } @@ -335,7 +350,6 @@ func getAppleGPUInfo() string { if err != nil { return "" } - // Extract just the chipset/model lines lines := strings.Split(string(out), "\n") var gpuLines []string for _, line := range lines { From 7d0cbf681bd0117a3823d70fef1b70f8d94db413 Mon Sep 17 00:00:00 2001 From: Alec Fong Date: Fri, 27 Feb 2026 18:05:44 -0800 Subject: [PATCH 2/2] perf(analytics): timeout parent process info collection at 100ms The ps commands on macOS can be slow under load, so wrap getParentProcessInfo in the same 100ms timeout used for GPU info. --- pkg/analytics/parentprocess.go | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/pkg/analytics/parentprocess.go b/pkg/analytics/parentprocess.go index 8a5d07b3..d30046dd 100644 --- a/pkg/analytics/parentprocess.go +++ b/pkg/analytics/parentprocess.go @@ -6,10 +6,29 @@ import ( "runtime" "strconv" "strings" + "time" ) // getParentProcessInfo returns the name and full command line of the parent process. +// Times out after 100ms to avoid blocking the CLI. func getParentProcessInfo() (name, cmdline string) { + type result struct { + name, cmdline string + } + ch := make(chan result, 1) + go func() { + n, c := getParentProcessInfoSync() + ch <- result{name: n, cmdline: c} + }() + select { + case r := <-ch: + return r.name, r.cmdline + case <-time.After(100 * time.Millisecond): + return "", "" + } +} + +func getParentProcessInfoSync() (name, cmdline string) { ppid := os.Getppid() if ppid <= 0 { return "", ""