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,
) -> 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)
}
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()
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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)?;