-
-
Notifications
You must be signed in to change notification settings - Fork 767
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Improve IpAddr/SocketAddr serialization by avoiding Display #2001
Conversation
6639830
to
857a805
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would you be able to share your benchmark showing 4x faster serialization to JSON?
🤦 Yes use std::net::Ipv4Addr;
fn main() {
let mut buf = [0u8; 15];
for _ in 0..10_000_000 {
ser_ip(&mut buf, &Ipv4Addr::new(127, 10, 0, 1));
}
}
#[inline(never)]
fn ser_ip(buf: &mut [u8], thing: &Ipv4Addr) {
serde_json::to_writer(buf, thing).unwrap();
}
I'm aware this is not a typical way to do benchmarking in the Rust community, but I find it is much more stable than using |
Would it be worth comparing against an unsafe version that removes the zero initialization of the whole buffer and the utf8 validation? My expectation from benchmarking |
In this case, it appears the utf8 validation is ~30% of the benchmark's runtime. Adding As far as I can tell, leaving the buffer uninitialized doesn't help at all. But initializing it with
As far as I can tell, there are no bounds checks emitted. It looks like LLVM correctly figures out that the buffer is large enough. After these improvements, the big hog in the benchmark is calling |
Thanks -- LGTM once tests pass. |
I've made the tests pass; do we want to give the same treatment to |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, looks good.
Yes I am open to optimizing SocketAddrV4 and the V6 types too, if it matters to anyone.
I'm opening a draft PR because I'd appreciate feedback, but this is definitely not done.
In some profiling, I've found that serializing
Ipv4Addr
to JSON is disproportionately slow. This (currently crude) patch is ~4x faster. I'm no expert on integer formatting,but I think I can improve the implementation by runningDone. The algorithm is faster.cargo expand
onitoa
then pasting in the chunks I need. As far as I can tell, going throughitoa
's public interface is not faster than this code because LLVM keeps theitoa::Buffer
in memory.Is there any concern with not using
std::fmt::Display
? As far as I can tell from experimenting, there's basically no opportunity to make the standard library formatting code faster because it uses so much dynamic dispatch.