Skip to content

Commit c322a71

Browse files
committed
host: cache static system info on AIX to avoid repeated subprocess spawns
1 parent f2a5cfa commit c322a71

1 file changed

Lines changed: 73 additions & 39 deletions

File tree

host/host_aix.go

Lines changed: 73 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"encoding/binary"
1010
"os"
1111
"strings"
12+
"sync"
1213

1314
"github.com/shirou/gopsutil/v4/internal/common"
1415
)
@@ -29,14 +30,39 @@ func getInvoker() common.Invoker {
2930
return invoke
3031
}
3132

32-
func HostIDWithContext(ctx context.Context) (string, error) {
33-
out, err := getInvoker().CommandWithContext(ctx, "uname", "-u")
34-
if err != nil {
35-
return "", err
36-
}
33+
// Static host information is cached because these values (hardware ID,
34+
// platform name, OS version, kernel version, architecture) do not change
35+
// at runtime. Caching avoids spawning subprocesses on repeated queries.
36+
var (
37+
hostIDOnce sync.Once
38+
hostIDVal string
39+
hostIDErr error
40+
41+
platformOnce sync.Once
42+
platformVal string
43+
familyVal string
44+
versionVal string
45+
platformErr error
46+
47+
kernelVerOnce sync.Once
48+
kernelVerVal string
49+
kernelVerErr error
50+
51+
kernelArchOnce sync.Once
52+
kernelArchVal string
53+
kernelArchErr error
54+
)
3755

38-
// The command always returns an extra newline, so we make use of Split() to get only the first line
39-
return strings.Split(string(out), "\n")[0], nil
56+
func HostIDWithContext(ctx context.Context) (string, error) {
57+
hostIDOnce.Do(func() {
58+
out, err := getInvoker().CommandWithContext(ctx, "uname", "-u")
59+
if err != nil {
60+
hostIDErr = err
61+
return
62+
}
63+
hostIDVal = strings.Split(string(out), "\n")[0]
64+
})
65+
return hostIDVal, hostIDErr
4066
}
4167

4268
func BootTimeWithContext(ctx context.Context) (btime uint64, err error) {
@@ -104,46 +130,54 @@ func UsersWithContext(_ context.Context) ([]UserStat, error) {
104130
return ret, nil
105131
}
106132

107-
// Much of this function could be static. However, to be future proofed, I've made it call the OS for the information in all instances.
133+
// PlatformInformationWithContext returns the platform name, family, and OS
134+
// version. These are immutable system identifiers cached after first query.
108135
func PlatformInformationWithContext(ctx context.Context) (platform, family, version string, err error) {
109-
// Set the platform (which should always, and only be, "AIX") from `uname -s`
110-
out, err := getInvoker().CommandWithContext(ctx, "uname", "-s")
111-
if err != nil {
112-
return "", "", "", err
113-
}
114-
platform = strings.TrimRight(string(out), "\n")
115-
116-
// Set the family
117-
family = strings.TrimRight(string(out), "\n")
118-
119-
// Set the version
120-
out, err = getInvoker().CommandWithContext(ctx, "oslevel")
121-
if err != nil {
122-
return "", "", "", err
123-
}
124-
version = strings.TrimRight(string(out), "\n")
136+
platformOnce.Do(func() {
137+
out, err := getInvoker().CommandWithContext(ctx, "uname", "-s")
138+
if err != nil {
139+
platformErr = err
140+
return
141+
}
142+
platformVal = strings.TrimRight(string(out), "\n")
143+
familyVal = platformVal
125144

126-
return platform, family, version, nil
145+
out, err = getInvoker().CommandWithContext(ctx, "oslevel")
146+
if err != nil {
147+
platformErr = err
148+
return
149+
}
150+
versionVal = strings.TrimRight(string(out), "\n")
151+
})
152+
return platformVal, familyVal, versionVal, platformErr
127153
}
128154

155+
// KernelVersionWithContext returns the kernel version (e.g., "7300-03-00-2446").
156+
// This is an immutable system identifier cached after first query.
129157
func KernelVersionWithContext(ctx context.Context) (version string, err error) {
130-
out, err := getInvoker().CommandWithContext(ctx, "oslevel", "-s")
131-
if err != nil {
132-
return "", err
133-
}
134-
version = strings.TrimRight(string(out), "\n")
135-
136-
return version, nil
158+
kernelVerOnce.Do(func() {
159+
out, err := getInvoker().CommandWithContext(ctx, "oslevel", "-s")
160+
if err != nil {
161+
kernelVerErr = err
162+
return
163+
}
164+
kernelVerVal = strings.TrimRight(string(out), "\n")
165+
})
166+
return kernelVerVal, kernelVerErr
137167
}
138168

169+
// KernelArch returns the hardware architecture (e.g., "64").
170+
// This is an immutable system identifier cached after first query.
139171
func KernelArch() (arch string, err error) {
140-
out, err := getInvoker().Command("bootinfo", "-y")
141-
if err != nil {
142-
return "", err
143-
}
144-
arch = strings.TrimRight(string(out), "\n")
145-
146-
return arch, nil
172+
kernelArchOnce.Do(func() {
173+
out, err := getInvoker().Command("bootinfo", "-y")
174+
if err != nil {
175+
kernelArchErr = err
176+
return
177+
}
178+
kernelArchVal = strings.TrimRight(string(out), "\n")
179+
})
180+
return kernelArchVal, kernelArchErr
147181
}
148182

149183
func VirtualizationWithContext(ctx context.Context) (string, string, error) {

0 commit comments

Comments
 (0)