Skip to content

Commit 8902a4c

Browse files
committed
Optimize KV display performance by reducing branch prediction misses
1 parent fa762d4 commit 8902a4c

File tree

4 files changed

+30
-49
lines changed

4 files changed

+30
-49
lines changed

spdlog/src/formatter/full_formatter.rs

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -98,21 +98,7 @@ impl FullFormatter {
9898
dest.write_str("] ")?;
9999
dest.write_str(record.payload())?;
100100

101-
let kvs = record.key_values();
102-
if !kvs.is_empty() {
103-
dest.write_str(" { ")?;
104-
105-
let mut iter = kvs.peekable();
106-
while let Some((key, value)) = iter.next() {
107-
dest.write_str(key.as_str())?;
108-
dest.write_str("=")?;
109-
write!(dest, "{}", value)?;
110-
if iter.peek().is_some() {
111-
dest.write_str(", ")?;
112-
}
113-
}
114-
dest.write_str(" }")?;
115-
}
101+
record.key_values().write_to(dest)?;
116102

117103
if self.with_eol {
118104
dest.write_str(__EOL)?;

spdlog/src/formatter/journald_formatter.rs

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -49,21 +49,7 @@ impl JournaldFormatter {
4949
dest.write_str("] ")?;
5050
dest.write_str(record.payload())?;
5151

52-
let kvs = record.key_values();
53-
if !kvs.is_empty() {
54-
dest.write_str(" { ")?;
55-
56-
let mut iter = kvs.peekable();
57-
while let Some((key, value)) = iter.next() {
58-
dest.write_str(key.as_str())?;
59-
dest.write_str("=")?;
60-
write!(dest, "{}", value)?;
61-
if iter.peek().is_some() {
62-
dest.write_str(", ")?;
63-
}
64-
}
65-
dest.write_str(" }")?;
66-
}
52+
record.key_values().write_to(dest)?;
6753

6854
dest.write_str(__EOL)?;
6955

spdlog/src/formatter/pattern_formatter/pattern/kv.rs

Lines changed: 4 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -15,23 +15,9 @@ impl Pattern for KV {
1515
dest: &mut StringBuf,
1616
_ctx: &mut PatternContext,
1717
) -> crate::Result<()> {
18-
(|| -> Result<(), fmt::Error> {
19-
let kvs = record.key_values();
20-
if !kvs.is_empty() {
21-
dest.write_str("{ ")?;
22-
let mut iter = kvs.peekable();
23-
while let Some((key, value)) = iter.next() {
24-
dest.write_str(key.as_str())?;
25-
dest.write_str("=")?;
26-
write!(dest, "{}", value)?;
27-
if iter.peek().is_some() {
28-
dest.write_str(", ")?;
29-
}
30-
}
31-
dest.write_str(" }")?;
32-
}
33-
Ok(())
34-
})()
35-
.map_err(Error::FormatRecord)
18+
record
19+
.key_values()
20+
.write_to(dest)
21+
.map_err(Error::FormatRecord)
3622
}
3723
}

spdlog/src/kv.rs

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use std::{borrow::Cow, marker::PhantomData};
1+
use std::{borrow::Cow, fmt, marker::PhantomData};
22

33
use value_bag::{OwnedValueBag, ValueBag};
44

@@ -95,6 +95,29 @@ where
9595
phantom: PhantomData,
9696
}
9797
}
98+
99+
pub(crate) fn write_to(mut self, dest: &mut impl fmt::Write) -> fmt::Result {
100+
let first = self.next();
101+
if let Some((key, value)) = first {
102+
dest.write_str(" { ")?;
103+
104+
// Reduce branch prediction misses for performance
105+
// So we manually process the first KV pair
106+
dest.write_str(key.as_str())?;
107+
dest.write_str("=")?;
108+
write!(dest, "{}", value)?;
109+
110+
while let Some((key, value)) = self.next() {
111+
dest.write_str(", ")?;
112+
dest.write_str(key.as_str())?;
113+
dest.write_str("=")?;
114+
write!(dest, "{}", value)?;
115+
}
116+
117+
dest.write_str(" }")?;
118+
}
119+
Ok(())
120+
}
98121
}
99122

100123
impl<'a, I> Iterator for KeyValuesIter<'a, I>

0 commit comments

Comments
 (0)