Skip to content

Commit 5eb3069

Browse files
authored
Merge pull request #26 from lpgauth/perf/faster-decode
Skip zero-init of decode stack buffers
2 parents 2c0c4f1 + 314a59b commit 5eb3069

1 file changed

Lines changed: 29 additions & 11 deletions

File tree

native/torque_nif/src/serde_decode.rs

Lines changed: 29 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ use rustler::{Encoder, Env, NewBinary, Term};
1616
use serde::de::{self, DeserializeSeed, MapAccess, SeqAccess, Visitor};
1717
use serde::Deserialize;
1818
use std::fmt;
19+
use std::mem::MaybeUninit;
1920

2021
use crate::atoms;
2122
use crate::nif_util::make_tuple2;
@@ -40,6 +41,14 @@ fn make_binary_term(env: Env, s: &str) -> ERL_NIF_TERM {
4041
term.as_c_arg()
4142
}
4243

44+
/// View the initialized `count`-element prefix of a MaybeUninit stack array.
45+
///
46+
/// SAFETY: callers must have written `arr[..count]` before calling.
47+
#[inline]
48+
unsafe fn stack_slice(arr: &[MaybeUninit<ERL_NIF_TERM>], count: usize) -> &[ERL_NIF_TERM] {
49+
std::slice::from_raw_parts(arr.as_ptr() as *const ERL_NIF_TERM, count)
50+
}
51+
4352
/// Try to create a sub-binary; fall back to copy if the str is not in the input buffer.
4453
#[inline]
4554
fn make_str_term(env: Env, input: InputRef, s: &str) -> ERL_NIF_TERM {
@@ -189,7 +198,8 @@ impl<'de, 'a> Visitor<'de> for TermVisitor<'a> {
189198
let input = self.input;
190199

191200
if hint <= STACK_SIZE {
192-
let mut stack: [ERL_NIF_TERM; STACK_SIZE] = [0; STACK_SIZE];
201+
let mut stack: [MaybeUninit<ERL_NIF_TERM>; STACK_SIZE] =
202+
[MaybeUninit::uninit(); STACK_SIZE];
193203
let mut count = 0;
194204

195205
while count < STACK_SIZE {
@@ -199,19 +209,23 @@ impl<'de, 'a> Visitor<'de> for TermVisitor<'a> {
199209
depth: child_depth,
200210
})? {
201211
Some(term) => {
202-
stack[count] = term;
212+
stack[count].write(term);
203213
count += 1;
204214
}
205215
None => {
206216
return Ok(unsafe {
207-
enif_make_list_from_array(env.as_c_arg(), stack.as_ptr(), count as u32)
217+
enif_make_list_from_array(
218+
env.as_c_arg(),
219+
stack.as_ptr() as *const ERL_NIF_TERM,
220+
count as u32,
221+
)
208222
});
209223
}
210224
}
211225
}
212226

213227
let mut heap = Vec::with_capacity(STACK_SIZE * 2);
214-
heap.extend_from_slice(&stack[..count]);
228+
heap.extend(stack.iter().map(|s| unsafe { s.assume_init() }));
215229
while let Some(term) = seq.next_element_seed(TermSeed {
216230
env,
217231
input,
@@ -247,8 +261,10 @@ impl<'de, 'a> Visitor<'de> for TermVisitor<'a> {
247261
let input = self.input;
248262

249263
if hint <= STACK_SIZE {
250-
let mut key_stack: [ERL_NIF_TERM; STACK_SIZE] = [0; STACK_SIZE];
251-
let mut val_stack: [ERL_NIF_TERM; STACK_SIZE] = [0; STACK_SIZE];
264+
let mut key_stack: [MaybeUninit<ERL_NIF_TERM>; STACK_SIZE] =
265+
[MaybeUninit::uninit(); STACK_SIZE];
266+
let mut val_stack: [MaybeUninit<ERL_NIF_TERM>; STACK_SIZE] =
267+
[MaybeUninit::uninit(); STACK_SIZE];
252268
let mut count = 0;
253269

254270
while count < STACK_SIZE {
@@ -259,20 +275,22 @@ impl<'de, 'a> Visitor<'de> for TermVisitor<'a> {
259275
input,
260276
depth: child_depth,
261277
})?;
262-
key_stack[count] = key;
263-
val_stack[count] = val;
278+
key_stack[count].write(key);
279+
val_stack[count].write(val);
264280
count += 1;
265281
}
266282
None => {
267-
return build_map(env, &key_stack[..count], &val_stack[..count], count);
283+
let keys = unsafe { stack_slice(&key_stack, count) };
284+
let vals = unsafe { stack_slice(&val_stack, count) };
285+
return build_map(env, keys, vals, count);
268286
}
269287
}
270288
}
271289

272290
let mut keys = Vec::with_capacity(STACK_SIZE * 2);
273291
let mut vals = Vec::with_capacity(STACK_SIZE * 2);
274-
keys.extend_from_slice(&key_stack[..count]);
275-
vals.extend_from_slice(&val_stack[..count]);
292+
keys.extend(key_stack.iter().map(|s| unsafe { s.assume_init() }));
293+
vals.extend(val_stack.iter().map(|s| unsafe { s.assume_init() }));
276294
while let Some(key) = map.next_key_seed(KeySeed { env, input })? {
277295
let val = map.next_value_seed(TermSeed {
278296
env,

0 commit comments

Comments
 (0)