mirror of
https://github.com/minio/minio.git
synced 2025-11-09 13:39:46 -05:00
storage write call path optimizations (#11805)
- write in o_dsync instead of o_direct for smaller objects to avoid unaligned double Write() situations that may arise for smaller objects < 128KiB - avoid fallocate() as its not useful since we do not use Append() semantics anymore, fallocate is not useful for streaming I/O we can save on a syscall - createFile() doesn't need to validate `bucket` name with a Lstat() call since createFile() is only used to write at `minioTmpBucket` - use io.Copy() when writing unAligned writes to allow usage of ReadFrom() from *os.File providing zero buffer writes().
This commit is contained in:
@@ -19,6 +19,7 @@
|
||||
package ioutil
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
"os"
|
||||
|
||||
@@ -188,33 +189,15 @@ const directioAlignSize = 4096
|
||||
// the file opened for writes with syscall.O_DIRECT flag.
|
||||
func CopyAligned(w *os.File, r io.Reader, alignedBuf []byte, totalSize int64) (int64, error) {
|
||||
// Writes remaining bytes in the buffer.
|
||||
writeUnaligned := func(w *os.File, buf []byte) (remainingWritten int, err error) {
|
||||
var n int
|
||||
remaining := len(buf)
|
||||
// The following logic writes the remainging data such that it writes whatever best is possible (aligned buffer)
|
||||
// in O_DIRECT mode and remaining (unaligned buffer) in non-O_DIRECT mode.
|
||||
remainingAligned := (remaining / directioAlignSize) * directioAlignSize
|
||||
remainingAlignedBuf := buf[:remainingAligned]
|
||||
remainingUnalignedBuf := buf[remainingAligned:]
|
||||
if len(remainingAlignedBuf) > 0 {
|
||||
n, err = w.Write(remainingAlignedBuf)
|
||||
if err != nil {
|
||||
return remainingWritten, err
|
||||
}
|
||||
remainingWritten += n
|
||||
writeUnaligned := func(w *os.File, buf []byte) (remainingWritten int64, err error) {
|
||||
// Disable O_DIRECT on fd's on unaligned buffer
|
||||
// perform an amortized Fdatasync(fd) on the fd at
|
||||
// the end, this is performed by the caller before
|
||||
// closing 'w'.
|
||||
if err = disk.DisableDirectIO(w); err != nil {
|
||||
return remainingWritten, err
|
||||
}
|
||||
if len(remainingUnalignedBuf) > 0 {
|
||||
// Write on O_DIRECT fds fail if buffer is not 4K aligned, hence disable O_DIRECT.
|
||||
if err = disk.DisableDirectIO(w); err != nil {
|
||||
return remainingWritten, err
|
||||
}
|
||||
n, err = w.Write(remainingUnalignedBuf)
|
||||
if err != nil {
|
||||
return remainingWritten, err
|
||||
}
|
||||
remainingWritten += n
|
||||
}
|
||||
return remainingWritten, nil
|
||||
return io.Copy(w, bytes.NewReader(buf))
|
||||
}
|
||||
|
||||
var written int64
|
||||
@@ -232,21 +215,23 @@ func CopyAligned(w *os.File, r io.Reader, alignedBuf []byte, totalSize int64) (i
|
||||
return written, err
|
||||
}
|
||||
buf = buf[:nr]
|
||||
var nw int
|
||||
var nw int64
|
||||
if len(buf)%directioAlignSize == 0 {
|
||||
var n int
|
||||
// buf is aligned for directio write()
|
||||
nw, err = w.Write(buf)
|
||||
n, err = w.Write(buf)
|
||||
nw = int64(n)
|
||||
} else {
|
||||
// buf is not aligned, hence use writeUnaligned()
|
||||
nw, err = writeUnaligned(w, buf)
|
||||
}
|
||||
if nw > 0 {
|
||||
written += int64(nw)
|
||||
written += nw
|
||||
}
|
||||
if err != nil {
|
||||
return written, err
|
||||
}
|
||||
if nw != len(buf) {
|
||||
if nw != int64(len(buf)) {
|
||||
return written, io.ErrShortWrite
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user