-
Notifications
You must be signed in to change notification settings - Fork 8
add parsing variant that doesn't allocate #83
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
Conversation
Signed-off-by: Petros Angelatos <petrosagg@gmail.com>
e81561c to
0d76ca8
Compare
ParkMyCar
left a comment
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.
Nice!
| // * 3 bytes for the largest possible exponent (308) | ||
| // An example of such maximal float value is f64::from_bits(0x8008000000000000) whose | ||
| // decimal representation is '-1.1125369292536007e-308' | ||
| const MAX_LEN: usize = 24; |
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.
This makes sense to me! Just double checked and ryu also sizes their buffer with 24 bytes so these seems quite safe
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.
Nice to see it validated elsewhere!
|
|
||
| let mut buf = [0u8; MAX_LEN + 1]; | ||
| let mut unwritten = &mut buf[..MAX_LEN]; | ||
| write!(unwritten, "{:e}", n).unwrap(); |
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.
IIRC the write! macro has a decent amount of machinery internally that it might be nice to bypass, not a huge priority though.
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.
Talked on slack, doesn't seem to be much we do here so leaving it as-is
| // decimal representation is '-1.1125369292536007e-308' | ||
| const MAX_LEN: usize = 24; | ||
|
|
||
| let mut buf = [0u8; MAX_LEN + 1]; |
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.
It seems like this +1 is to ensure the last byte is a null character for the C String? mind documenting that?
0d76ca8 to
132d7ae
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.
The f32 conversion is not correct.
fn main() {
println!("{}", 4.8f32 as f64);
println!("{}", 4.8f64 as f64);
}
prints
4.800000190734863
4.8
132d7ae to
b906875
Compare
|
@antiguru good catch! Pushed a change to fix this. I added a generic method for both float sizes that calls into the appropriate stringify method |
antiguru
left a comment
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 for addressing the f32 issue!
dec/src/decimal.rs
Outdated
| self.from_float(n) | ||
| } | ||
|
|
||
| /// Converts an `f64` to a `Decimal<N>`. |
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.
The description is now incorrect. Also, we should ensure that we only pass f32|f64 here, and not accidentally f128 in the future.
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.
Indeed, I'll fix the description. I'm not super concerned about ensuring statically that T is either f32 or f64 since you can't cause UB by doing that but I will document it for the future engineer
Signed-off-by: Petros Angelatos <petrosagg@gmail.com>
b906875 to
2af10a8
Compare
Signed-off-by: Petros Angelatos <petrosagg@gmail.com>
4d012b1 to
c7db9da
Compare
This PR fixes a regression introduced in #83 which started serializing floats using their scientific notation, which is much shorter than the decimal notation and therefore faster. It turns out that conversion from string to decimal is syntactic instead of semantic. This means that the strings "12" and "1.2E2", which are semantically the same number, parse into a different Decimal instance. This PR fixes the regression by serializing to the decimal representation. The overall improvement from 0.4.9 is much more mild as a result. ``` parse_decimal time: [2.4036 µs 2.4180 µs 2.4389 µs] change: [-22.670% -21.979% -21.336%] (p = 0.00 < 0.05) Performance has improved. ``` Signed-off-by: Petros Angelatos <petrosagg@gmail.com>
This PR fixes a regression introduced in #83 which started serializing floats using their scientific notation, which is much shorter than the decimal notation and therefore faster. It turns out that conversion from string to decimal is syntactic instead of semantic. This means that the strings "12" and "1.2E2", which are semantically the same number, parse into a different Decimal instance. This PR fixes the regression by serializing to the decimal representation. The overall improvement from 0.4.9 is much more mild as a result. ``` parse_decimal time: [2.4036 µs 2.4180 µs 2.4389 µs] change: [-22.670% -21.979% -21.336%] (p = 0.00 < 0.05) Performance has improved. ``` Signed-off-by: Petros Angelatos <petrosagg@gmail.com>
This PR fixes a regression introduced in #83 which started serializing floats using their scientific notation, which is much shorter than the decimal notation and therefore faster. It turns out that conversion from string to decimal is syntactic instead of semantic. This means that the strings "12" and "1.2E2", which are semantically the same number, parse into a different Decimal instance. This PR fixes the regression by serializing to the decimal representation. The overall improvement from 0.4.9 is much more mild as a result. ``` parse_decimal time: [2.4036 µs 2.4180 µs 2.4389 µs] change: [-22.670% -21.979% -21.336%] (p = 0.00 < 0.05) Performance has improved. ``` Signed-off-by: Petros Angelatos <petrosagg@gmail.com>
This PR improves the routines that convert
f64values intoDecimal<N>values by avoiding allocating large strings. The performance comes from:I have included a benchmark for the
from_f64method which shows a 4x improvement: