Skip to content

Commit 17197b7

Browse files
committed
perf(drivers): Use smallvec for AvailBufferToken
While it is hypothetically possible to have send and receive buffers of sizes up to that of the virt queue, in reality we only ever have up to 2 items here. smallvec lets us handle this case very efficiently while still theoretically allowing for larger amounts of items. Signed-off-by: Jens Reidel <[email protected]>
1 parent 399f818 commit 17197b7

File tree

4 files changed

+40
-22
lines changed

4 files changed

+40
-22
lines changed

src/drivers/fs/virtio_fs.rs

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use alloc::vec::Vec;
44
use core::str;
55

66
use pci_types::InterruptLine;
7+
use smallvec::SmallVec;
78
use virtio::FeatureBits;
89
use virtio::fs::ConfigVolatileFieldAccess;
910
use volatile::VolatileRef;
@@ -168,23 +169,26 @@ impl FuseInterface for VirtioFsDriver {
168169
payload: cmd_payload_opt,
169170
} = cmd;
170171
let send = if let Some(cmd_payload) = cmd_payload_opt {
171-
vec![
172+
SmallVec::from_buf([
172173
BufferElem::Sized(cmd_headers),
173174
BufferElem::Vector(cmd_payload),
174-
]
175+
])
175176
} else {
176-
vec![BufferElem::Sized(cmd_headers)]
177+
let mut vec = SmallVec::new();
178+
vec.push(BufferElem::Sized(cmd_headers));
179+
vec
177180
};
178181

179182
let rsp_headers = Box::<RspHeader<O>, _>::new_uninit_in(DeviceAlloc);
180183
let recv = if rsp_payload_len == 0 {
181-
vec![BufferElem::Sized(rsp_headers)]
184+
let mut vec = SmallVec::new();
185+
vec.push(BufferElem::Sized(rsp_headers));
186+
vec
182187
} else {
183-
let rsp_payload = Vec::with_capacity_in(rsp_payload_len as usize, DeviceAlloc);
184-
vec![
188+
SmallVec::from_buf([
185189
BufferElem::Sized(rsp_headers),
186-
BufferElem::Vector(rsp_payload),
187-
]
190+
BufferElem::Vector(Vec::with_capacity_in(rsp_payload_len as usize, DeviceAlloc)),
191+
])
188192
};
189193

190194
let buffer_tkn = AvailBufferToken::new(send, recv).unwrap();

src/drivers/net/virtio/mod.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ cfg_if::cfg_if! {
1313
use alloc::boxed::Box;
1414
use alloc::vec::Vec;
1515

16+
use smallvec::SmallVec;
1617
use smoltcp::phy::{Checksum, ChecksumCapabilities};
1718
use smoltcp::wire::{ETHERNET_HEADER_LEN, EthernetFrame, Ipv4Packet, Ipv6Packet};
1819
use virtio::net::{ConfigVolatileFieldAccess, Hdr, HdrF};
@@ -114,14 +115,14 @@ impl RxQueues {
114115
fn fill_queue(vq: &mut VirtQueue, num_packets: u16, packet_size: u32) {
115116
for _ in 0..num_packets {
116117
let buff_tkn = match AvailBufferToken::new(
117-
vec![],
118-
vec![
118+
SmallVec::new(),
119+
SmallVec::from_buf([
119120
BufferElem::Sized(Box::<Hdr, _>::new_uninit_in(DeviceAlloc)),
120121
BufferElem::Vector(Vec::with_capacity_in(
121122
packet_size.try_into().unwrap(),
122123
DeviceAlloc,
123124
)),
124-
],
125+
]),
125126
) {
126127
Ok(tkn) => tkn,
127128
Err(_vq_err) => {
@@ -292,8 +293,8 @@ impl NetworkDriver for VirtioNetDriver {
292293
}
293294

294295
let buff_tkn = AvailBufferToken::new(
295-
vec![BufferElem::Sized(header), BufferElem::Vector(packet)],
296-
vec![],
296+
SmallVec::from_buf([BufferElem::Sized(header), BufferElem::Vector(packet)]),
297+
SmallVec::new(),
297298
)
298299
.unwrap();
299300

src/drivers/virtio/virtqueue/mod.rs

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ use core::mem::MaybeUninit;
2020
use core::{mem, ptr};
2121

2222
use enum_dispatch::enum_dispatch;
23+
use smallvec::SmallVec;
2324
use virtio::{le32, le64, pvirtq, virtq};
2425

2526
use self::error::VirtqError;
@@ -396,8 +397,8 @@ impl BufferElem {
396397
/// respective virtqueue.
397398
/// The maximum number of descriptors per buffer is bounded by the size of the virtqueue.
398399
pub struct AvailBufferToken {
399-
pub(crate) send_buff: Vec<BufferElem>,
400-
pub(crate) recv_buff: Vec<BufferElem>,
400+
pub(crate) send_buff: SmallVec<[BufferElem; 2]>,
401+
pub(crate) recv_buff: SmallVec<[BufferElem; 2]>,
401402
}
402403

403404
pub(crate) struct UsedDeviceWritableBuffer {
@@ -450,7 +451,7 @@ impl UsedDeviceWritableBuffer {
450451
}
451452

452453
pub(crate) struct UsedBufferToken {
453-
pub send_buff: Vec<BufferElem>,
454+
pub send_buff: SmallVec<[BufferElem; 2]>,
454455
pub used_recv_buff: UsedDeviceWritableBuffer,
455456
}
456457

@@ -459,7 +460,7 @@ impl UsedBufferToken {
459460
Self {
460461
send_buff: tkn.send_buff,
461462
used_recv_buff: UsedDeviceWritableBuffer {
462-
elems: tkn.recv_buff.into(),
463+
elems: tkn.recv_buff.into_vec().into(),
463464
remaining_written_len: written_len,
464465
},
465466
}
@@ -492,7 +493,10 @@ impl AvailBufferToken {
492493
/// ```
493494
/// they must split the structure after the send part and provide the respective part via the send argument and the respective other
494495
/// part via the recv argument.
495-
pub fn new(send_buff: Vec<BufferElem>, recv_buff: Vec<BufferElem>) -> Result<Self, VirtqError> {
496+
pub fn new(
497+
send_buff: SmallVec<[BufferElem; 2]>,
498+
recv_buff: SmallVec<[BufferElem; 2]>,
499+
) -> Result<Self, VirtqError> {
496500
if send_buff.is_empty() && recv_buff.is_empty() {
497501
return Err(VirtqError::BufferNotSpecified);
498502
}

src/drivers/vsock/mod.rs

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use alloc::vec::Vec;
88
use core::mem;
99

1010
use pci_types::InterruptLine;
11+
use smallvec::SmallVec;
1112
use virtio::FeatureBits;
1213
use virtio::vsock::Hdr;
1314

@@ -28,14 +29,14 @@ use crate::mm::device_alloc::DeviceAlloc;
2829
fn fill_queue(vq: &mut VirtQueue, num_packets: u16, packet_size: u32) {
2930
for _ in 0..num_packets {
3031
let buff_tkn = match AvailBufferToken::new(
31-
vec![],
32-
vec![
32+
SmallVec::new(),
33+
SmallVec::from_buf([
3334
BufferElem::Sized(Box::<Hdr, _>::new_uninit_in(DeviceAlloc)),
3435
BufferElem::Vector(Vec::with_capacity_in(
3536
packet_size.try_into().unwrap(),
3637
DeviceAlloc,
3738
)),
38-
],
39+
]),
3940
) {
4041
Ok(tkn) => tkn,
4142
Err(_vq_err) => {
@@ -171,7 +172,15 @@ impl TxQueue {
171172
result
172173
};
173174

174-
let buff_tkn = AvailBufferToken::new(vec![BufferElem::Vector(packet)], vec![]).unwrap();
175+
let buff_tkn = AvailBufferToken::new(
176+
{
177+
let mut vec = SmallVec::new();
178+
vec.push(BufferElem::Vector(packet));
179+
vec
180+
},
181+
SmallVec::new(),
182+
)
183+
.unwrap();
175184

176185
vq.dispatch(buff_tkn, false, BufferType::Direct).unwrap();
177186

0 commit comments

Comments
 (0)