Skip to content

Commit f3ece39

Browse files
committed
Improve numbers encoding
Copy the bytes into a buffer instead of destructuring them. On my machine it's an about 15% performance improvement for f64. For all types, even if it's 16-bit only, the resulting assembly has less instructions: https://godbolt.org/z/ov97Pq43j
1 parent 30fe080 commit f3ece39

File tree

1 file changed

+22
-14
lines changed

1 file changed

+22
-14
lines changed

src/core/enc.rs

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,9 @@ impl Encode for TypeNum<u16> {
6969
match u8::try_from(self.value) {
7070
Ok(x) => TypeNum::new(self.type_, x).encode(writer)?,
7171
Err(_) => {
72-
let [x0, x1] = self.value.to_be_bytes();
73-
writer.push(&[self.type_ | 0x19, x0, x1])?
72+
let mut buf = [self.type_ | 0x19, 0, 0];
73+
buf[1..3].copy_from_slice(&self.value.to_be_bytes());
74+
writer.push(&buf)?
7475
}
7576
}
7677
Ok(())
@@ -83,8 +84,9 @@ impl Encode for TypeNum<u32> {
8384
match u16::try_from(self.value) {
8485
Ok(x) => TypeNum::new(self.type_, x).encode(writer)?,
8586
Err(_) =>{
86-
let [x0, x1, x2, x3] = self.value.to_be_bytes();
87-
writer.push(&[self.type_ | 0x1a, x0, x1, x2, x3])?;
87+
let mut buf = [self.type_ | 0x1a, 0, 0, 0, 0];
88+
buf[1..5].copy_from_slice(&self.value.to_be_bytes());
89+
writer.push(&buf)?;
8890
}
8991
}
9092
Ok(())
@@ -97,8 +99,9 @@ impl Encode for TypeNum<u64> {
9799
match u32::try_from(self.value) {
98100
Ok(x) => TypeNum::new(self.type_, x).encode(writer)?,
99101
Err(_) => {
100-
let [x0, x1, x2, x3, x4, x5, x6, x7] = self.value.to_be_bytes();
101-
writer.push(&[self.type_ | 0x1b, x0, x1, x2, x3, x4, x5, x6, x7])?;
102+
let mut buf = [self.type_ | 0x1b, 0, 0, 0, 0, 0, 0, 0, 0];
103+
buf[1..9].copy_from_slice(&self.value.to_be_bytes());
104+
writer.push(&buf)?;
102105
}
103106
}
104107
Ok(())
@@ -349,35 +352,39 @@ impl<T: Encode> Encode for types::Maybe<&'_ Option<T>> {
349352
impl Encode for half::f16 {
350353
#[inline]
351354
fn encode<W: Write>(&self, writer: &mut W) -> Result<(), Error<W::Error>> {
352-
let [x0, x1] = self.to_be_bytes();
353-
writer.push(&[marker::F16, x0, x1])?;
355+
let mut buf = [marker::F16, 0, 0];
356+
buf[1..3].copy_from_slice(&self.to_be_bytes());
357+
writer.push(&buf)?;
354358
Ok(())
355359
}
356360
}
357361

358362
impl Encode for types::F16 {
359363
#[inline]
360364
fn encode<W: Write>(&self, writer: &mut W) -> Result<(), Error<W::Error>> {
361-
let [x0, x1] = self.0.to_be_bytes();
362-
writer.push(&[marker::F16, x0, x1])?;
365+
let mut buf = [marker::F16, 0, 0];
366+
buf[1..3].copy_from_slice(&self.0.to_be_bytes());
367+
writer.push(&buf)?;
363368
Ok(())
364369
}
365370
}
366371

367372
impl Encode for f32 {
368373
#[inline]
369374
fn encode<W: Write>(&self, writer: &mut W) -> Result<(), Error<W::Error>> {
370-
let [x0, x1, x2, x3] = self.to_be_bytes();
371-
writer.push(&[marker::F32, x0, x1, x2, x3])?;
375+
let mut buf = [marker::F32, 0, 0, 0, 0];
376+
buf[1..5].copy_from_slice(&self.to_be_bytes());
377+
writer.push(&buf)?;
372378
Ok(())
373379
}
374380
}
375381

376382
impl Encode for f64 {
377383
#[inline]
378384
fn encode<W: Write>(&self, writer: &mut W) -> Result<(), Error<W::Error>> {
379-
let [x0, x1, x2, x3, x4, x5, x6, x7] = self.to_be_bytes();
380-
writer.push(&[marker::F64, x0, x1, x2, x3, x4, x5, x6, x7])?;
385+
let mut buf = [marker::F64, 0, 0, 0, 0, 0, 0, 0, 0];
386+
buf[1..9].copy_from_slice(&self.to_be_bytes());
387+
writer.push(&buf)?;
381388
Ok(())
382389
}
383390
}
@@ -478,6 +485,7 @@ fn test_encoded() -> anyhow::Result<()> {
478485
1.1f64, "0xfb3ff199999999999a";
479486
@ #[cfg(feature = "half-f16")] half::f16::from_f32(1.5), "0xf93e00";
480487
@ #[cfg(feature = "half-f16")] half::f16::from_f32(65504.0), "0xf97bff";
488+
types::F16(0x7bff), "0xf97bff";
481489
100000.0f32, "0xfa47c35000";
482490
3.4028234663852886e+38f32, "0xfa7f7fffff";
483491
1.0e+300f64, "0xfb7e37e43c8800759c";

0 commit comments

Comments
 (0)