Skip to content

Commit 06751c4

Browse files
jakebaileygopherbot
authored andcommitted
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 <[email protected]> LUCI-TryBot-Result: Go LUCI <[email protected]> Reviewed-by: Alex Brainman <[email protected]> Reviewed-by: Quim Muntal <[email protected]> Reviewed-by: Junyang Shao <[email protected]> Auto-Submit: Carlos Amedee <[email protected]>
1 parent c966f1c commit 06751c4

File tree

2 files changed

+27
-0
lines changed

2 files changed

+27
-0
lines changed

src/syscall/syscall_windows.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,12 +138,32 @@ func FormatMessage(flags uint32, msgsrc uint32, msgid uint32, langid uint32, buf
138138
return formatMessage(flags, uintptr(msgsrc), msgid, langid, buf, args)
139139
}
140140

141+
var errnoErrorCache sync.Map
142+
141143
func (e Errno) Error() string {
142144
// deal with special go errors
143145
idx := int(e - APPLICATION_ERROR)
144146
if 0 <= idx && idx < len(errors) {
145147
return errors[idx]
146148
}
149+
150+
cache := false
151+
switch e {
152+
case ERROR_FILE_NOT_FOUND, ERROR_PATH_NOT_FOUND:
153+
if cached, ok := errnoErrorCache.Load(e); ok {
154+
return cached.(string)
155+
}
156+
cache = true
157+
}
158+
159+
result := e.error()
160+
if cache {
161+
errnoErrorCache.Store(e, result)
162+
}
163+
return result
164+
}
165+
166+
func (e Errno) error() string {
147167
// ask windows for the remaining errors
148168
var flags uint32 = FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ARGUMENT_ARRAY | FORMAT_MESSAGE_IGNORE_INSERTS
149169
b := make([]uint16, 300)

src/syscall/syscall_windows_test.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -299,3 +299,10 @@ func FuzzUTF16FromString(f *testing.F) {
299299
}
300300
})
301301
}
302+
303+
func BenchmarkErrnoString(b *testing.B) {
304+
b.ReportAllocs()
305+
for b.Loop() {
306+
_ = syscall.Errno(2).Error()
307+
}
308+
}

0 commit comments

Comments
 (0)