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 <robert.bradford@intel.com>
This commit is contained in:
Rob Bradford 2023-01-10 14:28:29 +00:00
parent 67ff0d7819
commit ce51755109
8 changed files with 17 additions and 21 deletions

View File

@ -141,5 +141,5 @@ pub trait AsyncIo: Send {
user_data: u64, user_data: u64,
) -> AsyncIoResult<()>; ) -> AsyncIoResult<()>;
fn fsync(&mut self, user_data: Option<u64>) -> AsyncIoResult<()>; fn fsync(&mut self, user_data: Option<u64>) -> AsyncIoResult<()>;
fn complete(&mut self) -> Vec<(u64, i32)>; fn next_completed_request(&mut self) -> Option<(u64, i32)>;
} }

View File

@ -104,7 +104,7 @@ impl AsyncIo for FixedVhdAsync {
self.raw_file_async.fsync(user_data) self.raw_file_async.fsync(user_data)
} }
fn complete(&mut self) -> Vec<(u64, i32)> { fn next_completed_request(&mut self) -> Option<(u64, i32)> {
self.raw_file_async.complete() self.raw_file_async.next_completed_request()
} }
} }

View File

@ -101,7 +101,7 @@ impl AsyncIo for FixedVhdSync {
self.raw_file_sync.fsync(user_data) self.raw_file_sync.fsync(user_data)
} }
fn complete(&mut self) -> Vec<(u64, i32)> { fn next_completed_request(&mut self) -> Option<(u64, i32)> {
self.raw_file_sync.complete() self.raw_file_sync.next_completed_request()
} }
} }

View File

@ -97,7 +97,7 @@ impl AsyncIo for QcowSync {
.fsync_sync(user_data, &self.eventfd, &mut self.completion_list) .fsync_sync(user_data, &self.eventfd, &mut self.completion_list)
} }
fn complete(&mut self) -> Vec<(u64, i32)> { fn next_completed_request(&mut self) -> Option<(u64, i32)> {
self.completion_list.drain(..).collect() self.completion_list.pop()
} }
} }

View File

@ -155,13 +155,10 @@ impl AsyncIo for RawFileAsync {
Ok(()) Ok(())
} }
fn complete(&mut self) -> Vec<(u64, i32)> { fn next_completed_request(&mut self) -> Option<(u64, i32)> {
let cq = self.io_uring.completion(); self.io_uring
let mut completion_list = Vec::with_capacity(cq.len()); .completion()
for cq_entry in cq { .next()
completion_list.push((cq_entry.user_data(), cq_entry.result())); .map(|entry| (entry.user_data(), entry.result()))
}
completion_list
} }
} }

View File

@ -127,7 +127,7 @@ impl AsyncIo for RawFileSync {
Ok(()) Ok(())
} }
fn complete(&mut self) -> Vec<(u64, i32)> { fn next_completed_request(&mut self) -> Option<(u64, i32)> {
self.completion_list.drain(..).collect() self.completion_list.pop()
} }
} }

View File

@ -96,7 +96,7 @@ impl AsyncIo for VhdxSync {
.fsync_sync(user_data, &self.eventfd, &mut self.completion_list) .fsync_sync(user_data, &self.eventfd, &mut self.completion_list)
} }
fn complete(&mut self) -> Vec<(u64, i32)> { fn next_completed_request(&mut self) -> Option<(u64, i32)> {
self.completion_list.drain(..).collect() self.completion_list.pop()
} }
} }

View File

@ -244,8 +244,7 @@ impl BlockEpollHandler {
let mut read_ops = Wrapping(0); let mut read_ops = Wrapping(0);
let mut write_ops = Wrapping(0); let mut write_ops = Wrapping(0);
let completion_list = self.disk_image.complete(); while let Some((user_data, result)) = self.disk_image.next_completed_request() {
for (user_data, result) in completion_list {
let desc_index = user_data as u16; let desc_index = user_data as u16;
let mut request = self.find_inflight_request(desc_index)?; let mut request = self.find_inflight_request(desc_index)?;