1 // Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 // SPDX-License-Identifier: Apache-2.0 OR BSD-3-Clause 3 4 use criterion::{black_box, BatchSize, Criterion}; 5 use virtio_queue::{Queue, QueueOwnedT, QueueT}; 6 use vm_memory::{GuestAddress, GuestMemory, GuestMemoryMmap}; 7 8 use virtio_queue::mock::MockSplitQueue; 9 benchmark_queue(c: &mut Criterion)10 pub fn benchmark_queue(c: &mut Criterion) { 11 fn walk_queue<M: GuestMemory>(q: &mut Queue, mem: &M) -> (usize, usize) { 12 let mut num_chains = 0; 13 let mut num_descriptors = 0; 14 15 q.iter(mem).unwrap().for_each(|chain| { 16 num_chains += 1; 17 chain.for_each(|_| num_descriptors += 1); 18 }); 19 20 (num_chains, num_descriptors) 21 } 22 23 fn bench_queue<S, R>(c: &mut Criterion, bench_name: &str, setup: S, mut routine: R) 24 where 25 S: FnMut() -> Queue + Clone, 26 R: FnMut(Queue), 27 { 28 c.bench_function(bench_name, move |b| { 29 b.iter_batched( 30 setup.clone(), 31 |q| routine(black_box(q)), 32 BatchSize::SmallInput, 33 ) 34 }); 35 } 36 37 let mem = GuestMemoryMmap::<()>::from_ranges(&[(GuestAddress(0x0), 0x1_0000_0000)]).unwrap(); 38 39 let queue_with_chains = |num_chains, len, indirect| { 40 let mut mq = MockSplitQueue::new(&mem, 256); 41 for _ in 0..num_chains { 42 if indirect { 43 mq.add_indirect_chain(len).unwrap(); 44 } else { 45 mq.add_chain(len).unwrap(); 46 } 47 } 48 mq.create_queue().unwrap() 49 }; 50 51 let empty_queue = || { 52 let mq = MockSplitQueue::new(&mem, 256); 53 mq.create_queue().unwrap() 54 }; 55 56 for indirect in [false, true].iter().copied() { 57 bench_queue( 58 c, 59 &format!("single chain (indirect={})", indirect), 60 || queue_with_chains(1, 128, indirect), 61 |mut q| { 62 let (num_chains, num_descriptors) = walk_queue(&mut q, &mem); 63 assert_eq!(num_chains, 1); 64 assert_eq!(num_descriptors, 128); 65 }, 66 ); 67 68 bench_queue( 69 c, 70 &format!("multiple chains (indirect={})", indirect), 71 || queue_with_chains(128, 1, indirect), 72 |mut q| { 73 let (num_chains, num_descriptors) = walk_queue(&mut q, &mem); 74 assert_eq!(num_chains, 128); 75 assert_eq!(num_descriptors, 128); 76 }, 77 ); 78 } 79 80 bench_queue(c, "add used", empty_queue, |mut q| { 81 for _ in 0..128 { 82 q.add_used(&mem, 123, 0x1000).unwrap(); 83 } 84 }); 85 } 86