-
Notifications
You must be signed in to change notification settings - Fork 12.8k
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
Serialization performance regression #38021
Comments
The TrustedLen PR is in that range, so it's quite possibly that. It changed the implementation of extend_from_slice. git log --oneline --first-parent 5665bdf..cae6ab1 |
I don't see much difference, the new code should be almost equivalent. One uses a counted loop and the other a pointer = pointer.offset(1) loop, though. |
Ok just picking a recent rust commit to work off of (127a83d). Command line:
With that compiler I get the benchmark result
If I put in the old implementation for
Do you think that could be it? That's the kind of difference? The test case in the original issue is not affected by the change, though. |
That could be it. For me:
Can you try this case? For me this showed a 70% regression from 995μs to 1685μs. #![feature(test)]
extern crate serde;
extern crate serde_json;
extern crate test;
#[derive(Clone, Default)]
struct Area(u32);
impl serde::Serialize for Area {
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: serde::Serializer
{
let mut state = try!(serializer.serialize_struct("Area", 1));
try!(serializer.serialize_struct_elt(&mut state, "blockIds", &[(); 0]));
serializer.serialize_struct_end(state)
}
}
#[bench]
fn bench(b: &mut test::Bencher) {
let areas = vec![Area::default(); 65536];
let len = serde_json::to_string(&areas).unwrap().len();
let mut buf = Vec::with_capacity(len);
b.iter(|| {
buf.clear();
serde_json::to_writer(&mut buf, &areas).unwrap();
});
} |
oh wow. before test bench ... bench: 2,358,534 ns/iter (+/- 51,417) |
well something is regressing to a byte-by-byte loop there, and it's definitely .extend(slice.iter().cloned()), I thought SetLenOnDrop had worked around those (we used to have those for extend_from_slice too). |
Ok it's not the same thing. |
We've verified that putting back extend_from_slice's old implementation would work well, but I don't have a reduced test case. Would be ideal if .extend() could be fixed instead of the duplication. |
This is enough to reproduce I think. The .extend() loop is byte-by-byte (albeit unrolled in this case). https://gist.github.com/bluss/61c32daae1bd31d9d7605983df3ace5f#file-extend_from_slice-ll-L146 Rust code is below the llvm ir. |
The codegen issue is #38175, if this issue is resolved by other means (by reverting for example). |
Specialization for Extend<&T> for vec Specialize to use copy_from_slice when extending a Vec with &[T] where T: Copy. This specialization results in `.clone()` not being called in `extend_from_slice` and `extend` when the element is `Copy`. Fixes #38021
Between
rustc 1.14.0-nightly (5665bdf3e 2016-11-02)
andrustc 1.14.0-nightly (cae6ab1c4 2016-11-05)
all of my serialization benchmarks showed a ~50% regression. It affected all the libraries (Serde, json-rust, rustc-serialize). Deserialization was not affected. So far I have narrowed it down to the following code:On my linux laptop this regressed from 160μs to 220μs, on my mac laptop 215μs to 300μs.
cc @bluss who seems to know about
extend_from_slice
.The text was updated successfully, but these errors were encountered: