Skip to content

Commit 3c20438

Browse files
eryugeybergwolf
authored andcommitted
transport: pre-allocate VecDeque to avoid expending at runtime
Expending VecDeque might be expensive, so pre-allocating a vecDeque with a fixed 64 capacity and hope it could hold all slices we need. And it will expand if it's not big enough anyway. Signed-off-by: Eryu Guan <[email protected]>
1 parent 8c3b49a commit 3c20438

File tree

1 file changed

+47
-43
lines changed

1 file changed

+47
-43
lines changed

src/transport/virtiofs/mod.rs

Lines changed: 47 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -46,9 +46,7 @@ use std::ptr::copy_nonoverlapping;
4646

4747
use virtio_queue::DescriptorChain;
4848
use vm_memory::bitmap::{BitmapSlice, MS};
49-
use vm_memory::{
50-
Address, ByteValued, GuestMemory, GuestMemoryRegion, MemoryRegionAddress, VolatileSlice,
51-
};
49+
use vm_memory::{Address, ByteValued, GuestMemory, GuestMemoryRegion, MemoryRegionAddress};
5250

5351
use super::{Error, FileReadWriteVolatile, FileVolatileSlice, IoBuffers, Reader, Result, Writer};
5452

@@ -73,28 +71,31 @@ impl<'a> Reader<'a> {
7371
M::Target: GuestMemory + Sized,
7472
{
7573
let mut total_len: usize = 0;
76-
let buffers = desc_chain
77-
.readable()
78-
.map(|desc| {
79-
// Verify that summing the descriptor sizes does not overflow.
80-
// This can happen if a driver tricks a device into reading more data than
81-
// fits in a `usize`.
82-
total_len = total_len
83-
.checked_add(desc.len() as usize)
84-
.ok_or(Error::DescriptorChainOverflow)?;
85-
86-
let region = mem
87-
.find_region(desc.addr())
88-
.ok_or(Error::FindMemoryRegion)?;
89-
let offset = desc
90-
.addr()
91-
.checked_sub(region.start_addr().raw_value())
92-
.unwrap();
74+
// Allocate VecDeque with 64 capacity and hope it could hold all slices to avoid expending
75+
// VecDeque repeatedly.
76+
let mut buffers = VecDeque::with_capacity(64);
77+
for desc in desc_chain.readable() {
78+
// Verify that summing the descriptor sizes does not overflow.
79+
// This can happen if a driver tricks a device into reading more data than
80+
// fits in a `usize`.
81+
total_len = total_len
82+
.checked_add(desc.len() as usize)
83+
.ok_or(Error::DescriptorChainOverflow)?;
84+
85+
let region = mem
86+
.find_region(desc.addr())
87+
.ok_or(Error::FindMemoryRegion)?;
88+
let offset = desc
89+
.addr()
90+
.checked_sub(region.start_addr().raw_value())
91+
.unwrap();
92+
93+
buffers.push_back(
9394
region
9495
.get_slice(MemoryRegionAddress(offset.raw_value()), desc.len() as usize)
95-
.map_err(Error::GuestMemoryError)
96-
})
97-
.collect::<Result<VecDeque<VolatileSlice<'a, MS<M::Target>>>>>()?;
96+
.map_err(Error::GuestMemoryError)?,
97+
);
98+
}
9899

99100
Ok(Reader {
100101
buffers: IoBuffers {
@@ -128,28 +129,31 @@ impl<'a> VirtioFsWriter<'a> {
128129
M::Target: GuestMemory + Sized,
129130
{
130131
let mut total_len: usize = 0;
131-
let buffers = desc_chain
132-
.writable()
133-
.map(|desc| {
134-
// Verify that summing the descriptor sizes does not overflow.
135-
// This can happen if a driver tricks a device into writing more data than
136-
// fits in a `usize`.
137-
total_len = total_len
138-
.checked_add(desc.len() as usize)
139-
.ok_or(Error::DescriptorChainOverflow)?;
140-
141-
let region = mem
142-
.find_region(desc.addr())
143-
.ok_or(Error::FindMemoryRegion)?;
144-
let offset = desc
145-
.addr()
146-
.checked_sub(region.start_addr().raw_value())
147-
.unwrap();
132+
// Allocate VecDeque with 64 capacity and hope it could hold all slices to avoid expending
133+
// VecDeque repeatedly.
134+
let mut buffers = VecDeque::with_capacity(64);
135+
for desc in desc_chain.writable() {
136+
// Verify that summing the descriptor sizes does not overflow.
137+
// This can happen if a driver tricks a device into writing more data than
138+
// fits in a `usize`.
139+
total_len = total_len
140+
.checked_add(desc.len() as usize)
141+
.ok_or(Error::DescriptorChainOverflow)?;
142+
143+
let region = mem
144+
.find_region(desc.addr())
145+
.ok_or(Error::FindMemoryRegion)?;
146+
let offset = desc
147+
.addr()
148+
.checked_sub(region.start_addr().raw_value())
149+
.unwrap();
150+
151+
buffers.push_back(
148152
region
149153
.get_slice(MemoryRegionAddress(offset.raw_value()), desc.len() as usize)
150-
.map_err(Error::GuestMemoryError)
151-
})
152-
.collect::<Result<VecDeque<VolatileSlice<'a, MS<M::Target>>>>>()?;
154+
.map_err(Error::GuestMemoryError)?,
155+
)
156+
}
153157

154158
Ok(VirtioFsWriter {
155159
buffers: IoBuffers {

0 commit comments

Comments
 (0)