From 9ab461b1c2e19194f2f2482db59b46558242ba2f Mon Sep 17 00:00:00 2001 From: Harry Thomas Date: Tue, 19 Apr 2022 15:53:04 -0400 Subject: [PATCH 1/2] moved benches from inside pnet_packet/src/ethernet.rs to pnet_packet/benches/packet_benchmarks.rs; added inlining to pnet_macros to increase speed of parsing data into packet --- pnet_macros/src/decorator.rs | 19 ++++++++ pnet_macros_support/src/packet.rs | 12 +++++ pnet_packet/Cargo.toml | 3 ++ pnet_packet/benches/packet_benchmarks.rs | 56 ++++++++++++++++++++++++ pnet_packet/src/ethernet.rs | 42 ------------------ 5 files changed, 90 insertions(+), 42 deletions(-) create mode 100644 pnet_packet/benches/packet_benchmarks.rs diff --git a/pnet_macros/src/decorator.rs b/pnet_macros/src/decorator.rs index 7a628b52..5e3cf057 100644 --- a/pnet_macros/src/decorator.rs +++ b/pnet_macros/src/decorator.rs @@ -67,6 +67,7 @@ impl Packet { } } +#[inline] pub fn generate_packet( s: &syn::DataStruct, name: String, @@ -91,6 +92,7 @@ pub fn generate_packet( Ok(tts) } +#[inline] fn generate_packet_struct(packet: &Packet) -> proc_macro2::TokenStream { let items = &[ (packet.packet_name(), "PacketData"), @@ -115,6 +117,7 @@ fn generate_packet_struct(packet: &Packet) -> proc_macro2::TokenStream { } } +#[inline] fn make_type(ty_str: String, endianness_important: bool) -> Result { if let Some((size, endianness, spec)) = parse_ty(&ty_str[..]) { if !endianness_important || size <= 8 || spec == EndiannessSpecified::Yes { @@ -138,6 +141,7 @@ fn make_type(ty_str: String, endianness_important: bool) -> Result } } +#[inline] fn make_packet(s: &syn::DataStruct, name: String) -> Result { let mut fields = Vec::new(); let mut payload_span = None; @@ -351,6 +355,7 @@ fn make_packet(s: &syn::DataStruct, name: String) -> Result { } /// Return the processed length expression for a packet. +#[inline] fn parse_length_expr( tts: &[proc_macro2::TokenTree], field_names: &[String], @@ -423,6 +428,7 @@ fn parse_length_expr( Ok(tokens_packet) } +#[inline] fn generate_packet_impl( packet: &Packet, mutable: bool, @@ -644,6 +650,7 @@ fn generate_packet_impl( )) } +#[inline] fn generate_packet_impls( packet: &Packet, ) -> Result<(proc_macro2::TokenStream, PayloadBounds, String), Error> { @@ -663,6 +670,7 @@ fn generate_packet_impls( .ok_or_else(|| Error::new(Span::call_site(), "generate_packet_impls failed")) } +#[inline] fn generate_packet_size_impls( packet: &Packet, size: &str, @@ -690,6 +698,7 @@ fn generate_packet_size_impls( Ok(quote! { #(#tts)* }) } +#[inline] fn generate_packet_trait_impls( packet: &Packet, payload_bounds: &PayloadBounds, @@ -748,6 +757,7 @@ fn generate_packet_trait_impls( Ok(quote! { #(#tts)* }) } +#[inline] fn generate_iterables(packet: &Packet) -> Result { let name = &packet.base_name; @@ -795,6 +805,7 @@ fn generate_iterables(packet: &Packet) -> Result Result { let get_fields = generate_get_fields(packet); @@ -825,6 +836,7 @@ fn generate_converters(packet: &Packet) -> Result Result { let mut field_fmt_str = String::new(); let mut get_fields = String::new(); @@ -862,6 +874,7 @@ fn generate_debug_impls(packet: &Packet) -> Result String { let base_offset = bit_offset / 8; @@ -1694,6 +1712,7 @@ fn current_offset(bit_offset: usize, offset_fns: &[String]) -> String { .fold(base_offset.to_string(), |a, b| a + " + " + &b[..]) } +#[inline] fn generate_get_fields(packet: &Packet) -> String { let mut gets = String::new(); diff --git a/pnet_macros_support/src/packet.rs b/pnet_macros_support/src/packet.rs index 72ff09bc..303b98a2 100644 --- a/pnet_macros_support/src/packet.rs +++ b/pnet_macros_support/src/packet.rs @@ -64,6 +64,7 @@ macro_rules! impl_index { impl<'p> Index<$index_t> for $t<'p> { type Output = $output_t; + #[inline] fn index(&self, index: $index_t) -> &$output_t { &self.as_slice().index(index) } @@ -74,6 +75,7 @@ macro_rules! impl_index { macro_rules! impl_index_mut { ($t:ident, $index_t:ty, $output_t:ty) => { impl<'p> IndexMut<$index_t> for $t<'p> { + #[inline] fn index_mut(&mut self, index: $index_t) -> &mut $output_t { self.as_mut_slice().index_mut(index) } @@ -92,6 +94,7 @@ pub enum PacketData<'p> { impl<'p> PacketData<'p> { /// Get a slice of the packet data. + #[inline] pub fn as_slice(&self) -> &[u8] { match self { &PacketData::Owned(ref data) => data.deref(), @@ -100,11 +103,13 @@ impl<'p> PacketData<'p> { } /// No-op - returns `self`. + #[inline] pub fn to_immutable(self) -> PacketData<'p> { self } /// A length of the packet data. + #[inline] pub fn len(&self) -> usize { self.as_slice().len() } @@ -127,6 +132,7 @@ pub enum MutPacketData<'p> { impl<'p> MutPacketData<'p> { /// Get packet data as a slice. + #[inline] pub fn as_slice(&self) -> &[u8] { match self { &MutPacketData::Owned(ref data) => data.deref(), @@ -135,6 +141,7 @@ impl<'p> MutPacketData<'p> { } /// Get packet data as a mutable slice. + #[inline] pub fn as_mut_slice(&mut self) -> &mut [u8] { match self { &mut MutPacketData::Owned(ref mut data) => data.deref_mut(), @@ -143,6 +150,7 @@ impl<'p> MutPacketData<'p> { } /// Get an immutable version of packet data. + #[inline] pub fn to_immutable(self) -> PacketData<'p> { match self { MutPacketData::Owned(data) => PacketData::Owned(data), @@ -151,6 +159,7 @@ impl<'p> MutPacketData<'p> { } /// Get a length of data in the packet. + #[inline] pub fn len(&self) -> usize { self.as_slice().len() } @@ -179,6 +188,7 @@ pub trait PrimitiveValues { impl PrimitiveValues for pnet_base::MacAddr { type T = (u8, u8, u8, u8, u8, u8); + #[inline] fn to_primitive_values(&self) -> (u8, u8, u8, u8, u8, u8) { (self.0, self.1, self.2, self.3, self.4, self.5) } @@ -186,6 +196,7 @@ impl PrimitiveValues for pnet_base::MacAddr { impl PrimitiveValues for ::std::net::Ipv4Addr { type T = (u8, u8, u8, u8); + #[inline] fn to_primitive_values(&self) -> (u8, u8, u8, u8) { let octets = self.octets(); @@ -195,6 +206,7 @@ impl PrimitiveValues for ::std::net::Ipv4Addr { impl PrimitiveValues for ::std::net::Ipv6Addr { type T = (u16, u16, u16, u16, u16, u16, u16, u16); + #[inline] fn to_primitive_values(&self) -> (u16, u16, u16, u16, u16, u16, u16, u16) { let segments = self.segments(); diff --git a/pnet_packet/Cargo.toml b/pnet_packet/Cargo.toml index c5a77770..d4d0d71a 100644 --- a/pnet_packet/Cargo.toml +++ b/pnet_packet/Cargo.toml @@ -16,5 +16,8 @@ pnet_base = { path = "../pnet_base", version = "0.29.0" } pnet_macros_support = { path = "../pnet_macros_support", version = "0.29.0" } pnet_macros = { path = "../pnet_macros", version = "0.29.0" } +[dev-dependencies] +hex = "0.4.3" + [build-dependencies] glob = "0.3.0" diff --git a/pnet_packet/benches/packet_benchmarks.rs b/pnet_packet/benches/packet_benchmarks.rs new file mode 100644 index 00000000..3889d135 --- /dev/null +++ b/pnet_packet/benches/packet_benchmarks.rs @@ -0,0 +1,56 @@ +#![feature(test)] +extern crate test; +use test::{Bencher, black_box}; + +use pnet_packet::ethernet::EthernetPacket; +use pnet_packet::ethernet::MutableEthernetPacket; +use pnet_packet::ipv4::MutableIpv4Packet; +use pnet_base::MacAddr; +use pnet_packet::Packet; +use pnet_packet::ipv4::Ipv4Packet; + +#[bench] +fn bench_packet_new_constructor(b: &mut Bencher) { + let buffer = vec![0; 20]; + b.iter(|| EthernetPacket::new(black_box(&buffer)).unwrap()); +} + +#[bench] +fn bench_packet_get_source(b: &mut Bencher) { + let buffer = vec![0; 20]; + let packet = EthernetPacket::new(&buffer).unwrap(); + b.iter(|| black_box(packet.get_source())); +} + +#[bench] +fn bench_packet_set_source_black_box(b: &mut Bencher) { + let mut buffer = vec![0; 20]; + let mut packet = MutableEthernetPacket::new(&mut buffer).unwrap(); + let mac = MacAddr::new(1, 2, 3, 4, 5, 6); + b.iter(|| packet.set_source(black_box(mac))); +} + +#[bench] +fn bench_packet_mutable_to_immutable(b: &mut Bencher) { + let mut buffer = vec![0; 20]; + let mut packet = MutableEthernetPacket::new(&mut buffer).unwrap(); + b.iter(|| black_box(packet.to_immutable())); +} + +#[bench] +fn bench_packet_immutable_to_immutable(b: &mut Bencher) { + let mut buffer = vec![0; 20]; + let mut packet = EthernetPacket::new(&mut buffer).unwrap(); + b.iter(|| black_box(packet.to_immutable())); +} + +#[bench] +fn bench_ipv4_parsing(b: &mut Bencher) { + let data = hex::decode("000c291ce319ecf4bbd93e7d08004500002e1b6540008006cd76c0a8c887c0a8c8151a3707d0dd6abb2b1f5fd25150180402120f000068656c6c6f0a").unwrap(); + let ethernet = EthernetPacket::new(&data).unwrap(); + let payload = ethernet.payload().clone(); + b.iter(|| + Ipv4Packet::new(black_box(&payload)) + ); + +} diff --git a/pnet_packet/src/ethernet.rs b/pnet_packet/src/ethernet.rs index 1c57a5d9..8f9f984b 100644 --- a/pnet_packet/src/ethernet.rs +++ b/pnet_packet/src/ethernet.rs @@ -171,45 +171,3 @@ fn ether_type_to_str() { assert_eq!(format!("{}", unknown), "unknown"); } -#[cfg(all(test, feature = "benchmark"))] -mod packet_benchmarks { - use super::*; - use test::{Bencher, black_box}; - - use util::MacAddr; - - #[bench] - fn bench_packet_new_constructor(b: &mut Bencher) { - let buffer = vec![0; 20]; - b.iter(|| EthernetPacket::new(black_box(&buffer)).unwrap()); - } - - #[bench] - fn bench_packet_get_source(b: &mut Bencher) { - let buffer = vec![0; 20]; - let packet = EthernetPacket::new(&buffer).unwrap(); - b.iter(|| black_box(packet.get_source())); - } - - #[bench] - fn bench_packet_set_source_black_box(b: &mut Bencher) { - let mut buffer = vec![0; 20]; - let mut packet = MutableEthernetPacket::new(&mut buffer).unwrap(); - let mac = MacAddr::new(1, 2, 3, 4, 5, 6); - b.iter(|| packet.set_source(black_box(mac))); - } - - #[bench] - fn bench_packet_mutable_to_immutable(b: &mut Bencher) { - let mut buffer = vec![0; 20]; - let mut packet = MutableEthernetPacket::new(&mut buffer).unwrap(); - b.iter(|| black_box(packet.to_immutable())); - } - - #[bench] - fn bench_packet_immutable_to_immutable(b: &mut Bencher) { - let mut buffer = vec![0; 20]; - let mut packet = EthernetPacket::new(&mut buffer).unwrap(); - b.iter(|| black_box(packet.to_immutable())); - } -} From 7b2ddc9e51bc98962a30400295909c0af33cc650 Mon Sep 17 00:00:00 2001 From: Harry Thomas Date: Tue, 19 Apr 2022 18:13:44 -0400 Subject: [PATCH 2/2] changed benches to criterion so to stay on stable toolchain --- pnet_packet/Cargo.toml | 6 +++ pnet_packet/benches/packet_benchmarks.rs | 67 +++++++++++++++--------- 2 files changed, 49 insertions(+), 24 deletions(-) diff --git a/pnet_packet/Cargo.toml b/pnet_packet/Cargo.toml index d4d0d71a..7728ea54 100644 --- a/pnet_packet/Cargo.toml +++ b/pnet_packet/Cargo.toml @@ -18,6 +18,12 @@ pnet_macros = { path = "../pnet_macros", version = "0.29.0" } [dev-dependencies] hex = "0.4.3" +criterion = {version = "0.3.5", features = ["html_reports"]} #added HTML feature becuase of the annoying warnings when running the tests [build-dependencies] glob = "0.3.0" + +[[bench]] +name = "bench_pnet_packet" +path = "benches/packet_benchmarks.rs" +harness = false \ No newline at end of file diff --git a/pnet_packet/benches/packet_benchmarks.rs b/pnet_packet/benches/packet_benchmarks.rs index 3889d135..97070ffe 100644 --- a/pnet_packet/benches/packet_benchmarks.rs +++ b/pnet_packet/benches/packet_benchmarks.rs @@ -1,6 +1,5 @@ -#![feature(test)] -extern crate test; -use test::{Bencher, black_box}; +//Using criterion so that we dont need to use the test framework which requires nightly toolchain +use criterion::{criterion_group, criterion_main, Criterion, black_box}; use pnet_packet::ethernet::EthernetPacket; use pnet_packet::ethernet::MutableEthernetPacket; @@ -9,48 +8,68 @@ use pnet_base::MacAddr; use pnet_packet::Packet; use pnet_packet::ipv4::Ipv4Packet; -#[bench] -fn bench_packet_new_constructor(b: &mut Bencher) { + +fn bench_packet_new_constructor(c: &mut Criterion) { let buffer = vec![0; 20]; - b.iter(|| EthernetPacket::new(black_box(&buffer)).unwrap()); + c.bench_function("EthernetPacket New Packet", |b| { + b.iter(|| + EthernetPacket::new(black_box(&buffer)).unwrap() + ); + }); } -#[bench] -fn bench_packet_get_source(b: &mut Bencher) { +fn bench_packet_get_source(c: &mut Criterion) { let buffer = vec![0; 20]; let packet = EthernetPacket::new(&buffer).unwrap(); - b.iter(|| black_box(packet.get_source())); + c.bench_function("EthernetPacket Get Source", |b| { + b.iter(|| + black_box(packet.get_source()) + ); + }); } -#[bench] -fn bench_packet_set_source_black_box(b: &mut Bencher) { +fn bench_packet_set_source_black_box(c: &mut Criterion) { let mut buffer = vec![0; 20]; let mut packet = MutableEthernetPacket::new(&mut buffer).unwrap(); let mac = MacAddr::new(1, 2, 3, 4, 5, 6); - b.iter(|| packet.set_source(black_box(mac))); + c.bench_function("EthernetPacket Set Source", |b| { + b.iter(|| + packet.set_source(black_box(mac)) + ); + }); } -#[bench] -fn bench_packet_mutable_to_immutable(b: &mut Bencher) { +fn bench_packet_mutable_to_immutable(c: &mut Criterion) { let mut buffer = vec![0; 20]; let mut packet = MutableEthernetPacket::new(&mut buffer).unwrap(); - b.iter(|| black_box(packet.to_immutable())); + c.bench_function("Mutable to Immutable", |b| { + b.iter(|| + black_box(packet.to_immutable()) + ); + }); } -#[bench] -fn bench_packet_immutable_to_immutable(b: &mut Bencher) { +fn bench_packet_immutable_to_immutable(c: &mut Criterion) { let mut buffer = vec![0; 20]; let mut packet = EthernetPacket::new(&mut buffer).unwrap(); - b.iter(|| black_box(packet.to_immutable())); + c.bench_function("Immutable to Immutable", |b| { + b.iter(|| + black_box(packet.to_immutable()) + ); + }); } -#[bench] -fn bench_ipv4_parsing(b: &mut Bencher) { +fn bench_ipv4_parsing(c: &mut Criterion) { let data = hex::decode("000c291ce319ecf4bbd93e7d08004500002e1b6540008006cd76c0a8c887c0a8c8151a3707d0dd6abb2b1f5fd25150180402120f000068656c6c6f0a").unwrap(); let ethernet = EthernetPacket::new(&data).unwrap(); let payload = ethernet.payload().clone(); - b.iter(|| - Ipv4Packet::new(black_box(&payload)) - ); - + c.bench_function("IPV4 Parsing", |b| { + b.iter(|| + Ipv4Packet::new(black_box(&payload)) + ); + }); } + +criterion_group!(benches, bench_packet_new_constructor, bench_packet_get_source, bench_packet_set_source_black_box, bench_packet_mutable_to_immutable, bench_packet_immutable_to_immutable, bench_ipv4_parsing); + +criterion_main!(benches); \ No newline at end of file