Skip to content

Commit

Permalink
Optimize KV display performance by reducing branch prediction misses
Browse files Browse the repository at this point in the history
  • Loading branch information
SpriteOvO committed Feb 13, 2025
1 parent 7d29ea3 commit b517657
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 51 deletions.
16 changes: 1 addition & 15 deletions spdlog/src/formatter/full_formatter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,21 +98,7 @@ impl FullFormatter {
dest.write_str("] ")?;
dest.write_str(record.payload())?;

let kvs = record.key_values();
if !kvs.is_empty() {
dest.write_str(" { ")?;

let mut iter = kvs.peekable();
while let Some((key, value)) = iter.next() {
dest.write_str(key.as_str())?;
dest.write_str("=")?;
write!(dest, "{}", value)?;
if iter.peek().is_some() {
dest.write_str(", ")?;
}
}
dest.write_str(" }")?;
}
record.key_values().write_to(dest)?;

if self.with_eol {
dest.write_str(__EOL)?;
Expand Down
16 changes: 1 addition & 15 deletions spdlog/src/formatter/journald_formatter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,21 +49,7 @@ impl JournaldFormatter {
dest.write_str("] ")?;
dest.write_str(record.payload())?;

let kvs = record.key_values();
if !kvs.is_empty() {
dest.write_str(" { ")?;

let mut iter = kvs.peekable();
while let Some((key, value)) = iter.next() {
dest.write_str(key.as_str())?;
dest.write_str("=")?;
write!(dest, "{}", value)?;
if iter.peek().is_some() {
dest.write_str(", ")?;
}
}
dest.write_str(" }")?;
}
record.key_values().write_to(dest)?;

dest.write_str(__EOL)?;

Expand Down
24 changes: 4 additions & 20 deletions spdlog/src/formatter/pattern_formatter/pattern/kv.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
use std::fmt::{self, Write};

use crate::{
formatter::pattern_formatter::{Pattern, PatternContext},
Error, Record, StringBuf,
Expand All @@ -15,23 +13,9 @@ impl Pattern for KV {
dest: &mut StringBuf,
_ctx: &mut PatternContext,
) -> crate::Result<()> {
(|| -> Result<(), fmt::Error> {
let kvs = record.key_values();
if !kvs.is_empty() {
dest.write_str("{ ")?;
let mut iter = kvs.peekable();
while let Some((key, value)) = iter.next() {
dest.write_str(key.as_str())?;
dest.write_str("=")?;
write!(dest, "{}", value)?;
if iter.peek().is_some() {
dest.write_str(", ")?;
}
}
dest.write_str(" }")?;
}
Ok(())
})()
.map_err(Error::FormatRecord)
record
.key_values()
.write_to(dest)
.map_err(Error::FormatRecord)
}
}
25 changes: 24 additions & 1 deletion spdlog/src/kv.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::{borrow::Cow, marker::PhantomData};
use std::{borrow::Cow, fmt, marker::PhantomData};

use value_bag::{OwnedValueBag, ValueBag};

Expand Down Expand Up @@ -95,6 +95,29 @@ where
phantom: PhantomData,
}
}

pub(crate) fn write_to(mut self, dest: &mut impl fmt::Write) -> fmt::Result {
let first = self.next();
if let Some((key, value)) = first {
dest.write_str(" { ")?;

// Reduce branch prediction misses for performance
// So we manually process the first KV pair
dest.write_str(key.as_str())?;
dest.write_str("=")?;
write!(dest, "{}", value)?;

for (key, value) in self {
dest.write_str(", ")?;
dest.write_str(key.as_str())?;
dest.write_str("=")?;
write!(dest, "{}", value)?;
}

dest.write_str(" }")?;
}
Ok(())
}
}

impl<'a, I> Iterator for KeyValuesIter<'a, I>
Expand Down

0 comments on commit b517657

Please sign in to comment.