aboutsummaryrefslogtreecommitdiff
path: root/src/syscall/syscall_windows.go
diff options
context:
space:
mode:
authorJake Bailey <jacob.b.bailey@gmail.com>2025-03-24 16:01:06 -0700
committerGopher Robot <gobot@golang.org>2025-04-30 08:41:56 -0700
commit06751c455d89e09d29affc343ca9e38a02e2f5a2 (patch)
treee3a346888df2fa111e550a3f5f9170135bd777f0 /src/syscall/syscall_windows.go
parentc966f1c0c0e872773c38a6ddbd08df72726c8ba8 (diff)
downloadgo-06751c455d89e09d29affc343ca9e38a02e2f5a2.tar.xz
syscall: cache Errno.Error() on Windows
Windows is unlike the other OSs and depends on a syscall for most errors. This can be costly; cache the returned string for later reuse. This helps test caching, since errors are written out as string to the test ID, which are often PathErrors wrapping Errnos. For now, only cache ERROR_FILE_NOT_FOUND and ERROR_PATH_NOT_FOUND. goos: windows goarch: amd64 pkg: syscall cpu: Intel(R) Core(TM) i9-10900K CPU @ 3.70GHz │ old.txt │ new.txt │ │ sec/op │ sec/op vs base │ ErrnoString-20 1788.00n ± 1% 11.08n ± 1% -99.38% (p=0.000 n=10) │ old.txt │ new.txt │ │ B/op │ B/op vs base │ ErrnoString-20 48.00 ± 0% 0.00 ± 0% -100.00% (p=0.000 n=10) │ old.txt │ new.txt │ │ allocs/op │ allocs/op vs base │ ErrnoString-20 1.000 ± 0% 0.000 ± 0% -100.00% (p=0.000 n=10) For #72992 Change-Id: I9a0910fa6538772ffc64ef7670b44059a2c7d18c Reviewed-on: https://go-review.googlesource.com/c/go/+/667495 Reviewed-by: Carlos Amedee <carlos@golang.org> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Alex Brainman <alex.brainman@gmail.com> Reviewed-by: Quim Muntal <quimmuntal@gmail.com> Reviewed-by: Junyang Shao <shaojunyang@google.com> Auto-Submit: Carlos Amedee <carlos@golang.org>
Diffstat (limited to 'src/syscall/syscall_windows.go')
-rw-r--r--src/syscall/syscall_windows.go20
1 files changed, 20 insertions, 0 deletions
diff --git a/src/syscall/syscall_windows.go b/src/syscall/syscall_windows.go
index c4782031a4..f7fca07301 100644
--- a/src/syscall/syscall_windows.go
+++ b/src/syscall/syscall_windows.go
@@ -138,12 +138,32 @@ func FormatMessage(flags uint32, msgsrc uint32, msgid uint32, langid uint32, buf
return formatMessage(flags, uintptr(msgsrc), msgid, langid, buf, args)
}
+var errnoErrorCache sync.Map
+
func (e Errno) Error() string {
// deal with special go errors
idx := int(e - APPLICATION_ERROR)
if 0 <= idx && idx < len(errors) {
return errors[idx]
}
+
+ cache := false
+ switch e {
+ case ERROR_FILE_NOT_FOUND, ERROR_PATH_NOT_FOUND:
+ if cached, ok := errnoErrorCache.Load(e); ok {
+ return cached.(string)
+ }
+ cache = true
+ }
+
+ result := e.error()
+ if cache {
+ errnoErrorCache.Store(e, result)
+ }
+ return result
+}
+
+func (e Errno) error() string {
// ask windows for the remaining errors
var flags uint32 = FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ARGUMENT_ARRAY | FORMAT_MESSAGE_IGNORE_INSERTS
b := make([]uint16, 300)