block_util: Use SmallVec for I/O requests

The number of buffers in the request is usually one so by using SmallVec
the number of heap allocations can be significantly reduced.

DHAT reports:

Before:

dhat: Total:     1,166,412 bytes in 40,383 blocks

After:

dhat: Total:     623,852 bytes in 8,157 blocks

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
This commit is contained in:
Rob Bradford 2023-01-10 12:45:30 +00:00
parent e7a51cde78
commit 67ff0d7819
3 changed files with 7 additions and 3 deletions

1
Cargo.lock generated
View File

@ -88,6 +88,7 @@ dependencies = [
"libc",
"log",
"qcow",
"smallvec",
"thiserror",
"versionize",
"versionize_derive",

View File

@ -12,6 +12,7 @@ io-uring = "0.5.9"
libc = "0.2.139"
log = "0.4.17"
qcow = { path = "../qcow" }
smallvec = "1.10.0"
thiserror = "1.0.37"
versionize = "0.1.9"
versionize_derive = "0.1.4"

View File

@ -22,6 +22,7 @@ pub mod vhdx_sync;
use crate::async_io::{AsyncIo, AsyncIoError, AsyncIoResult};
use io_uring::{opcode, IoUring, Probe};
use smallvec::SmallVec;
use std::alloc::{alloc_zeroed, dealloc, Layout};
use std::cmp;
use std::convert::TryInto;
@ -195,7 +196,7 @@ pub struct AlignedOperation {
pub struct Request {
pub request_type: RequestType,
pub sector: u64,
pub data_descriptors: Vec<(GuestAddress, u32)>,
pub data_descriptors: SmallVec<[(GuestAddress, u32); 1]>,
pub status_addr: GuestAddress,
pub writeback: bool,
pub aligned_operations: Vec<AlignedOperation>,
@ -226,7 +227,7 @@ impl Request {
let mut req = Request {
request_type: request_type(desc_chain.memory(), hdr_desc_addr)?,
sector: sector(desc_chain.memory(), hdr_desc_addr)?,
data_descriptors: Vec::new(),
data_descriptors: SmallVec::with_capacity(1),
status_addr: GuestAddress(0),
writeback: true,
aligned_operations: Vec::new(),
@ -354,7 +355,8 @@ impl Request {
let request_type = self.request_type;
let offset = (sector << SECTOR_SHIFT) as libc::off_t;
let mut iovecs = Vec::with_capacity(self.data_descriptors.len());
let mut iovecs: SmallVec<[libc::iovec; 1]> =
SmallVec::with_capacity(self.data_descriptors.len());
for (data_addr, data_len) in &self.data_descriptors {
if *data_len == 0 {
continue;