Generalize Decodable impl for arrays to all types - #160111
Conversation
|
r? @mu001999 rustbot has assigned @mu001999. Use Why was this reviewer chosen?The reviewer was selected based on:
|
This comment has been minimized.
This comment has been minimized.
8ee8971 to
98eff47
Compare
|
@bors try @rust-timer queue |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
Generalize Decodable impl for arrays to all types
This comment has been minimized.
This comment has been minimized.
|
Finished benchmarking commit (8676bf1): comparison URL. Overall result: ❌ regressions - no action neededBenchmarking means the PR may be perf-sensitive. Consider adding rollup=never if this change is not fit for rolling up. @rustbot label: -S-waiting-on-perf -perf-regression Instruction countOur most reliable metric. Used to determine the overall result above. However, even this metric can be noisy.
Max RSS (memory usage)Results (primary -3.9%)A less reliable metric. May be of interest, but not used to determine the overall result above.
CyclesResults (secondary 1.7%)A less reliable metric. May be of interest, but not used to determine the overall result above.
Binary sizeThis perf run didn't have relevant results for this metric. Bootstrap: 491.747s -> 489.069s (-0.54%) |
|
Interesting. This is actually quite negative. The results are overwhelmingly red if you look at non-relevant results. I guess the early assert was there to avoid bound checks in the loop? Note: I found only one usage of this impl, which is for |
98eff47 to
95a4f1c
Compare
|
@bors try @rust-timer queue |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
Generalize Decodable impl for arrays to all types
| impl<D: Decoder, const N: usize> Decodable<D> for [u8; N] { | ||
| fn decode(d: &mut D) -> [u8; N] { | ||
| impl<D: Decoder, T: Decodable<D>, const N: usize> Decodable<D> for [T; N] { | ||
| fn decode(d: &mut D) -> [T; N] { | ||
| let len = d.read_usize(); | ||
| assert!(len == N); |
There was a problem hiding this comment.
Can we go further stop encoding and decoding len?
There was a problem hiding this comment.
Hm, I'm not sure, can we? I thought it's there for some reason, like compatibility with other list types. But I don't really know the rules of the serialization system.
I will try it out. This is called a few thousands times in many benchmarks, so it might have an impact.
There was a problem hiding this comment.
If you encode [T;2] and then [T;3] after it, it wouldn't be distinguishable from encoding [T;3] and then [T;2] after it, right? This is an issue for stable hashing, and it's why we also hash the length there.
There was a problem hiding this comment.
This is an issue for stable hashing, and it's why we also hash the length there.
Is it? It's equivalent to confusing (T, T) and (T, T, T). The type system prevents it. If we ever have such a case, we will have some kind of enum discriminant that changed somewhere.
There was a problem hiding this comment.
Or could we downgrade this to debug_assert at least?
There was a problem hiding this comment.
This is an issue for stable hashing, and it's why we also hash the length there.
Is it? It's equivalent to confusing
(T, T)and(T, T, T). The type system prevents it. If we ever have such a case, we will have some kind of enum discriminant that changed somewhere.
In stable hashing, the problem is that if in one compilation you hash [1, 2, 3], [4, 5], and in another [1, 2], [3, 4, 5], those would get the same hash, but clearly it's different compilation data.
I'm not sure if that's a potential problem also in decoding though.
There was a problem hiding this comment.
Where in the code could this happen? I only see Encodable/Decodable derived on types, and we know the exact length on those. Is there a place where we type erase something and decode blindly? But we would get some some type information from somewhere anyway, I suppose.
There was a problem hiding this comment.
I'm inclined to just drop the second commit and postpone this concern for later. I feel like I don't have a good way to actually figure out whether this is a problem or not and it feels somewhat orthogonal to the original purpose of this PR.
There was a problem hiding this comment.
I'm inclined to just drop the second commit
+1 to this
This comment has been minimized.
This comment has been minimized.
|
Finished benchmarking commit (7b88eb6): comparison URL. Overall result: ✅ improvements - no action neededBenchmarking means the PR may be perf-sensitive. Consider adding rollup=never if this change is not fit for rolling up. @rustbot label: -S-waiting-on-perf -perf-regression Instruction countOur most reliable metric. Used to determine the overall result above. However, even this metric can be noisy.
Max RSS (memory usage)Results (primary -1.2%, secondary 1.5%)A less reliable metric. May be of interest, but not used to determine the overall result above.
CyclesResults (primary 0.8%, secondary 0.4%)A less reliable metric. May be of interest, but not used to determine the overall result above.
Binary sizeThis perf run didn't have relevant results for this metric. Bootstrap: 489.658s -> 491.046s (0.28%) |
|
The @bors try @rust-timer queue |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
Generalize Decodable impl for arrays to all types
This comment has been minimized.
This comment has been minimized.
|
Finished benchmarking commit (13951c5): comparison URL. Overall result: no relevant changes - no action neededBenchmarking means the PR may be perf-sensitive. Consider adding rollup=never if this change is not fit for rolling up. @rustbot label: -S-waiting-on-perf -perf-regression Instruction countThis perf run didn't have relevant results for this metric. Max RSS (memory usage)Results (primary 0.5%, secondary -1.0%)A less reliable metric. May be of interest, but not used to determine the overall result above.
CyclesResults (primary -0.1%, secondary -6.8%)A less reliable metric. May be of interest, but not used to determine the overall result above.
Binary sizeResults (primary -0.1%, secondary -0.0%)A less reliable metric. May be of interest, but not used to determine the overall result above.
Bootstrap: 489.76s -> 488.544s (-0.25%) |
|
Not encoding len makes the metadata a tiny bit smaller which is cool, but otherwise there's not much impact. Let's decide based on how the discussion above settles. |
View all comments
This is almost the only impl that is not symetric with its Encodable counterpart. I tried to find out why in the history but it looks like this impl predates most of the generic symetric ones that are in this file, so it looks like it's not intentional.
I bumped into this randomly by changing a Vec to an array in some Mir types. The error was pretty confusing and It took me a while to figure out so I think it's worth generalizing this for somebody else in the future, even though it's technically not necessary at the moment.
We piggyback off ofWe useSmallVecimpl to avoid adding aDefaultbound orMaybeUninitunsafe dance. This moves the assert from the begining to the end of the loop.array::from_fn