optimize performance: reduce allocations, buffered I/O, and zero-copy reads

- Read path: eliminate redundant allocation in bsPerformCommand - remove
  the pre-allocation before bs.Read() and the append loop for zero-fill,
  use direct copy and in-place zero-fill instead
- parseHeader: use command pool (getCommand) instead of direct allocation,
  reducing GC pressure on the hot path
- Unmap: use a shared 1MB zero buffer instead of allocating per-descriptor,
  dramatically reducing allocations for large unmap operations
- Network I/O: add 256KB bufio.Writer to iSCSI connections, batching
  small PDU writes into fewer syscalls. Flush after txHandler completes

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Lei Xue
2026-03-14 19:03:30 +08:00
parent 729b450ac9
commit 16108ced95
5 changed files with 41 additions and 10 deletions

View File

@@ -159,11 +159,26 @@ func (bs *FileBackingStore) DataAdvise(offset, length int64, advise uint32) erro
return util.Fadvise(bs.file, offset, length, advise)
}
// unmapZeroBufSize is the size of the reusable zero buffer for unmap operations.
const unmapZeroBufSize = 1 << 20 // 1MB
// unmapZeroBuf is a pre-allocated zero buffer shared across unmap calls.
var unmapZeroBuf = make([]byte, unmapZeroBufSize)
func (bs *FileBackingStore) Unmap(descriptors []api.UnmapBlockDescriptor) error {
for _, desc := range descriptors {
zeros := make([]byte, desc.TL)
if _, err := bs.file.WriteAt(zeros, int64(desc.Offset)); err != nil {
return err
remaining := desc.TL
off := int64(desc.Offset)
for remaining > 0 {
writeLen := remaining
if writeLen > unmapZeroBufSize {
writeLen = unmapZeroBufSize
}
if _, err := bs.file.WriteAt(unmapZeroBuf[:writeLen], off); err != nil {
return err
}
off += int64(writeLen)
remaining -= writeLen
}
}
return nil