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:
Harshavardhana
2021-03-17 09:38:38 -07:00
committed by GitHub
parent 0eb146e1b2
commit 60b0f2324e
5 changed files with 49 additions and 107 deletions

View File

@@ -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
}