mirror of
https://github.com/golang/go
synced 2024-11-26 16:16:57 -07:00
os: avoid allocation in File.WriteString
Instead of alloc+copy to convert the string to a byte slice, do an unsafe conversion. Rely on the kernel not to scribble on the buffer during the write. Fixes #42406 Change-Id: I66f4838b43a11bcc3d67bbfa1706726318d55343 Reviewed-on: https://go-review.googlesource.com/c/go/+/268020 Trust: Josh Bleecher Snyder <josharian@gmail.com> Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com> Reviewed-by: Emmanuel Odeke <emmanuel@orijtech.com>
This commit is contained in:
parent
194b636f8f
commit
526ee96f49
@ -44,11 +44,13 @@ import (
|
||||
"errors"
|
||||
"internal/poll"
|
||||
"internal/testlog"
|
||||
"internal/unsafeheader"
|
||||
"io"
|
||||
"io/fs"
|
||||
"runtime"
|
||||
"syscall"
|
||||
"time"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// Name returns the name of the file as presented to Open.
|
||||
@ -246,7 +248,12 @@ func (f *File) Seek(offset int64, whence int) (ret int64, err error) {
|
||||
// WriteString is like Write, but writes the contents of string s rather than
|
||||
// a slice of bytes.
|
||||
func (f *File) WriteString(s string) (n int, err error) {
|
||||
return f.Write([]byte(s))
|
||||
var b []byte
|
||||
hdr := (*unsafeheader.Slice)(unsafe.Pointer(&b))
|
||||
hdr.Data = (*unsafeheader.String)(unsafe.Pointer(&s)).Data
|
||||
hdr.Cap = len(s)
|
||||
hdr.Len = len(s)
|
||||
return f.Write(b)
|
||||
}
|
||||
|
||||
// Mkdir creates a new directory with the specified name and permission
|
||||
|
@ -2773,3 +2773,21 @@ func TestReadFileProc(t *testing.T) {
|
||||
t.Fatalf("read %s: not newline-terminated: %q", name, data)
|
||||
}
|
||||
}
|
||||
|
||||
func TestWriteStringAlloc(t *testing.T) {
|
||||
if runtime.GOOS == "js" {
|
||||
t.Skip("js allocates a lot during File.WriteString")
|
||||
}
|
||||
d := t.TempDir()
|
||||
f, err := Create(filepath.Join(d, "whiteboard.txt"))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer f.Close()
|
||||
allocs := testing.AllocsPerRun(100, func() {
|
||||
f.WriteString("I will not allocate when passed a string longer than 32 bytes.\n")
|
||||
})
|
||||
if allocs != 0 {
|
||||
t.Errorf("expected 0 allocs for File.WriteString, got %v", allocs)
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user