From ce517551091df851f12e0e44b39c45af20745b57 Mon Sep 17 00:00:00 2001 From: Rob Bradford Date: Tue, 10 Jan 2023 14:28:29 +0000 Subject: [PATCH] block_util: Avoid intermediate completion queue allocation Rather than aggregate the completion list into an intermediate vector instead adjust the API to provide one completion item at a time. With DHAT this shows the number of heap allocations has decreased. Before: dhat: Total: 623,852 bytes in 8,157 blocks After: dhat: Total: 380,444 bytes in 3,469 blocks Signed-off-by: Rob Bradford --- block_util/src/async_io.rs | 2 +- block_util/src/fixed_vhd_async.rs | 4 ++-- block_util/src/fixed_vhd_sync.rs | 4 ++-- block_util/src/qcow_sync.rs | 4 ++-- block_util/src/raw_async.rs | 13 +++++-------- block_util/src/raw_sync.rs | 4 ++-- block_util/src/vhdx_sync.rs | 4 ++-- virtio-devices/src/block.rs | 3 +-- 8 files changed, 17 insertions(+), 21 deletions(-) diff --git a/block_util/src/async_io.rs b/block_util/src/async_io.rs index cb27b080e..6298dc068 100644 --- a/block_util/src/async_io.rs +++ b/block_util/src/async_io.rs @@ -141,5 +141,5 @@ pub trait AsyncIo: Send { user_data: u64, ) -> AsyncIoResult<()>; fn fsync(&mut self, user_data: Option) -> AsyncIoResult<()>; - fn complete(&mut self) -> Vec<(u64, i32)>; + fn next_completed_request(&mut self) -> Option<(u64, i32)>; } diff --git a/block_util/src/fixed_vhd_async.rs b/block_util/src/fixed_vhd_async.rs index 583375a5c..7b03d0118 100644 --- a/block_util/src/fixed_vhd_async.rs +++ b/block_util/src/fixed_vhd_async.rs @@ -104,7 +104,7 @@ impl AsyncIo for FixedVhdAsync { self.raw_file_async.fsync(user_data) } - fn complete(&mut self) -> Vec<(u64, i32)> { - self.raw_file_async.complete() + fn next_completed_request(&mut self) -> Option<(u64, i32)> { + self.raw_file_async.next_completed_request() } } diff --git a/block_util/src/fixed_vhd_sync.rs b/block_util/src/fixed_vhd_sync.rs index e9944d18e..256bc02a9 100644 --- a/block_util/src/fixed_vhd_sync.rs +++ b/block_util/src/fixed_vhd_sync.rs @@ -101,7 +101,7 @@ impl AsyncIo for FixedVhdSync { self.raw_file_sync.fsync(user_data) } - fn complete(&mut self) -> Vec<(u64, i32)> { - self.raw_file_sync.complete() + fn next_completed_request(&mut self) -> Option<(u64, i32)> { + self.raw_file_sync.next_completed_request() } } diff --git a/block_util/src/qcow_sync.rs b/block_util/src/qcow_sync.rs index 097bcfea3..1202fba0b 100644 --- a/block_util/src/qcow_sync.rs +++ b/block_util/src/qcow_sync.rs @@ -97,7 +97,7 @@ impl AsyncIo for QcowSync { .fsync_sync(user_data, &self.eventfd, &mut self.completion_list) } - fn complete(&mut self) -> Vec<(u64, i32)> { - self.completion_list.drain(..).collect() + fn next_completed_request(&mut self) -> Option<(u64, i32)> { + self.completion_list.pop() } } diff --git a/block_util/src/raw_async.rs b/block_util/src/raw_async.rs index 8891eea28..736c994f7 100644 --- a/block_util/src/raw_async.rs +++ b/block_util/src/raw_async.rs @@ -155,13 +155,10 @@ impl AsyncIo for RawFileAsync { Ok(()) } - fn complete(&mut self) -> Vec<(u64, i32)> { - let cq = self.io_uring.completion(); - let mut completion_list = Vec::with_capacity(cq.len()); - for cq_entry in cq { - completion_list.push((cq_entry.user_data(), cq_entry.result())); - } - - completion_list + fn next_completed_request(&mut self) -> Option<(u64, i32)> { + self.io_uring + .completion() + .next() + .map(|entry| (entry.user_data(), entry.result())) } } diff --git a/block_util/src/raw_sync.rs b/block_util/src/raw_sync.rs index 80c44daeb..b9b87e0a6 100644 --- a/block_util/src/raw_sync.rs +++ b/block_util/src/raw_sync.rs @@ -127,7 +127,7 @@ impl AsyncIo for RawFileSync { Ok(()) } - fn complete(&mut self) -> Vec<(u64, i32)> { - self.completion_list.drain(..).collect() + fn next_completed_request(&mut self) -> Option<(u64, i32)> { + self.completion_list.pop() } } diff --git a/block_util/src/vhdx_sync.rs b/block_util/src/vhdx_sync.rs index 769c3f713..678aedeba 100644 --- a/block_util/src/vhdx_sync.rs +++ b/block_util/src/vhdx_sync.rs @@ -96,7 +96,7 @@ impl AsyncIo for VhdxSync { .fsync_sync(user_data, &self.eventfd, &mut self.completion_list) } - fn complete(&mut self) -> Vec<(u64, i32)> { - self.completion_list.drain(..).collect() + fn next_completed_request(&mut self) -> Option<(u64, i32)> { + self.completion_list.pop() } } diff --git a/virtio-devices/src/block.rs b/virtio-devices/src/block.rs index d04819a95..93d2e1b47 100644 --- a/virtio-devices/src/block.rs +++ b/virtio-devices/src/block.rs @@ -244,8 +244,7 @@ impl BlockEpollHandler { let mut read_ops = Wrapping(0); let mut write_ops = Wrapping(0); - let completion_list = self.disk_image.complete(); - for (user_data, result) in completion_list { + while let Some((user_data, result)) = self.disk_image.next_completed_request() { let desc_index = user_data as u16; let mut request = self.find_inflight_request(desc_index)?;