From 8e5f39996aac02c9bd59e0b60d2d50a2d5bcdabe Mon Sep 17 00:00:00 2001 From: Mingun Date: Sat, 8 Jun 2024 15:12:32 +0500 Subject: [PATCH] Add #[inline] to methods implementing XmlSource MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit All methods called only once or two and inlining them in most cases increases performance of our benchmarks: > critcmp master element-parser -t 5 group element-parser master ----- -------------- ------ NsReader::read_resolved_event_into/trim_text = true 1.00 384.1±7.53µs ? ?/sec 1.05 404.0±7.44µs ? ?/sec One event/CData 1.00 58.2±1.12ns ? ?/sec 1.17 68.1±1.35ns ? ?/sec One event/Comment 1.00 150.9±2.88ns ? ?/sec 1.07 161.4±2.79ns ? ?/sec decode_and_parse_document_with_namespaces/rpm_filelists.xml 1.00 95.3±1.53µs 115.3 MB/sec 1.07 102.2±1.65µs 107.5 MB/sec escape_text/escaped_chars_long 1.16 1479.3±28.09ns ? ?/sec 1.00 1275.0±23.98ns ? ?/sec escape_text/escaped_chars_short 1.00 498.1±8.62ns ? ?/sec 1.06 526.6±10.80ns ? ?/sec escape_text/no_chars_to_escape_long 1.18 1045.1±19.96ns ? ?/sec 1.00 887.1±17.00ns ? ?/sec escape_text/no_chars_to_escape_short 1.29 21.0±0.35ns ? ?/sec 1.00 16.4±0.31ns ? ?/sec parse_document_nocopy_with_namespaces/libreoffice_document.fodt 1.00 512.4±9.74µs 106.6 MB/sec 1.07 546.2±10.20µs 100.0 MB/sec parse_document_nocopy_with_namespaces/rpm_filelists.xml 1.00 86.9±1.49µs 126.4 MB/sec 1.14 99.2±1.74µs 110.7 MB/sec parse_document_nocopy_with_namespaces/rpm_other.xml 1.00 140.2±2.71µs 157.9 MB/sec 1.06 148.7±2.71µs 148.9 MB/sec parse_document_nocopy_with_namespaces/rpm_primary.xml 1.00 191.1±3.57µs 106.1 MB/sec 1.09 207.9±3.79µs 97.5 MB/sec parse_document_nocopy_with_namespaces/rpm_primary2.xml 1.00 62.2±1.20µs 115.2 MB/sec 1.09 67.5±1.28µs 106.2 MB/sec parse_document_nocopy_with_namespaces/sample_1.xml 1.00 10.4±0.21µs 106.1 MB/sec 1.07 11.1±0.21µs 99.3 MB/sec parse_document_nocopy_with_namespaces/sample_ns.xml 1.00 8.5±0.16µs 85.5 MB/sec 1.07 9.0±0.18µs 80.0 MB/sec parse_document_nocopy_with_namespaces/sample_rss.xml 1.00 784.2±13.53µs 240.5 MB/sec 1.10 859.9±12.82µs 219.3 MB/sec parse_document_nocopy_with_namespaces/test_writer_ident.xml 1.00 29.0±0.50µs 146.2 MB/sec 1.06 30.8±0.55µs 138.0 MB/sec read_event/trim_text = false 1.00 201.4±4.31µs ? ?/sec 1.08 218.5±3.98µs ? ?/sec read_event/trim_text = true 1.00 191.2±3.40µs ? ?/sec 1.11 211.7±4.11µs ? ?/sec --- src/reader/buffered_reader.rs | 7 +++++++ src/reader/slice_reader.rs | 8 ++++++++ 2 files changed, 15 insertions(+) diff --git a/src/reader/buffered_reader.rs b/src/reader/buffered_reader.rs index 6f0515c6..459137b6 100644 --- a/src/reader/buffered_reader.rs +++ b/src/reader/buffered_reader.rs @@ -13,6 +13,7 @@ use crate::reader::{is_whitespace, BangType, Parser, Reader, Span, XmlSource}; macro_rules! impl_buffered_source { ($($lf:lifetime, $reader:tt, $async:ident, $await:ident)?) => { #[cfg(not(feature = "encoding"))] + #[inline] $($async)? fn remove_utf8_bom(&mut self) -> Result<()> { use crate::encoding::UTF8_BOM; @@ -31,6 +32,7 @@ macro_rules! impl_buffered_source { } #[cfg(feature = "encoding")] + #[inline] $($async)? fn detect_encoding(&mut self) -> Result> { loop { break match self $(.$reader)? .fill_buf() $(.$await)? { @@ -91,6 +93,7 @@ macro_rules! impl_buffered_source { Ok((&buf[start..], done)) } + #[inline] $($async)? fn read<$($lf,)? P: Parser>( &mut self, buf: &'b mut Vec, @@ -134,6 +137,7 @@ macro_rules! impl_buffered_source { Err(Error::Syntax(P::eof_error())) } + #[inline] $($async)? fn read_bang_element $(<$lf>)? ( &mut self, buf: &'b mut Vec, @@ -184,6 +188,7 @@ macro_rules! impl_buffered_source { Err(bang_type.to_err()) } + #[inline] $($async)? fn skip_whitespace(&mut self, position: &mut usize) -> Result<()> { loop { break match self $(.$reader)? .fill_buf() $(.$await)? { @@ -203,6 +208,7 @@ macro_rules! impl_buffered_source { } } + #[inline] $($async)? fn skip_one(&mut self, byte: u8) -> Result { // search byte must be within the ascii range debug_assert!(byte.is_ascii()); @@ -216,6 +222,7 @@ macro_rules! impl_buffered_source { } } + #[inline] $($async)? fn peek_one(&mut self) -> Result> { loop { break match self $(.$reader)? .fill_buf() $(.$await)? { diff --git a/src/reader/slice_reader.rs b/src/reader/slice_reader.rs index f0dda99e..6a5d8c5d 100644 --- a/src/reader/slice_reader.rs +++ b/src/reader/slice_reader.rs @@ -237,6 +237,7 @@ impl<'a> Reader<&'a [u8]> { /// that will be borrowed by events. This implementation provides a zero-copy deserialization impl<'a> XmlSource<'a, ()> for &'a [u8] { #[cfg(not(feature = "encoding"))] + #[inline] fn remove_utf8_bom(&mut self) -> Result<()> { if self.starts_with(crate::encoding::UTF8_BOM) { *self = &self[crate::encoding::UTF8_BOM.len()..]; @@ -245,6 +246,7 @@ impl<'a> XmlSource<'a, ()> for &'a [u8] { } #[cfg(feature = "encoding")] + #[inline] fn detect_encoding(&mut self) -> Result> { if let Some((enc, bom_len)) = crate::encoding::detect_encoding(self) { *self = &self[bom_len..]; @@ -253,6 +255,7 @@ impl<'a> XmlSource<'a, ()> for &'a [u8] { Ok(None) } + #[inline] fn read_bytes_until( &mut self, byte: u8, @@ -275,6 +278,7 @@ impl<'a> XmlSource<'a, ()> for &'a [u8] { } } + #[inline] fn read(&mut self, _buf: (), position: &mut usize) -> Result<&'a [u8]> { let mut parser = P::default(); @@ -290,6 +294,7 @@ impl<'a> XmlSource<'a, ()> for &'a [u8] { Err(Error::Syntax(P::eof_error())) } + #[inline] fn read_bang_element( &mut self, _buf: (), @@ -311,6 +316,7 @@ impl<'a> XmlSource<'a, ()> for &'a [u8] { Err(bang_type.to_err()) } + #[inline] fn skip_whitespace(&mut self, position: &mut usize) -> Result<()> { let whitespaces = self .iter() @@ -321,6 +327,7 @@ impl<'a> XmlSource<'a, ()> for &'a [u8] { Ok(()) } + #[inline] fn skip_one(&mut self, byte: u8) -> Result { // search byte must be within the ascii range debug_assert!(byte.is_ascii()); @@ -332,6 +339,7 @@ impl<'a> XmlSource<'a, ()> for &'a [u8] { } } + #[inline] fn peek_one(&mut self) -> Result> { Ok(self.first().copied()) }