Skip to content

add fill_tape_padded to skip the internal input copy - #472

Open
ranflarion wants to merge 1 commit into
simd-lite:mainfrom
ranflarion:ran/fill-tape-padded
Open

ranflarion wants to merge 1 commit into
simd-lite:mainfrom
ranflarion:ran/fill-tape-padded

Conversation

@ranflarion

Copy link
Copy Markdown

First half of #469: the padded entry point, without the UTF-8 validation skip (independent, can follow separately).

fill_tape_padded(s, len, buffers, tape) plus INPUT_PADDING. Callers that control the input layout supply the SIMD over-read padding themselves, skipping the O(len) copy fill_tape makes into its internal buffer: +2% to +7% on the shapes measured in #469, growing with document size.

With that copy gone stage 2 reads the same buffer string unescaping writes into, so the read side can no longer be a &[u8] argument (argument protectors under both borrow models, and noalias readonly). It becomes InputView, a pub(crate) pointer+len threaded through build_tape and the per-ISA parse_str, with build_tape taking *mut u8 for the write side. fill_tape still passes a disjoint copy, so that path is unchanged.

One correction to the issue: since 011d699 dropped NUL from the structural-or-whitespace tables the padding is not arbitrary, s[len] has to be structural or whitespace (b' ' works). Documented, and root_scalars_terminated_by_padding covers it.

tests/fill_tape_padded.rs pins the result against fill_tape node-for-node over lane-boundary escape positions, escapes landing against the padding, shared multi-row scratches, error paths and a random corpus. Miri-clean under Stacked and Tree Borrows on both aarch64 and x86_64, which may be useful for #446/#450; full suite, feature matrix, clippy and fmt green.

Happy to rename things or keep InputView out of parse_str's signature if you'd prefer.

@Licenser Licenser left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This largely looks good, I like the option to get moar speedddd! from it but there are a few things to adress

Comment thread src/lib.rs
Comment on lines +182 to +185
/// # Safety
///
/// The caller must guarantee `s.len() >= len + INPUT_PADDING`. Like [`fill_tape`], string
/// unescaping writes in place within the logical input.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of a # Safety comment pushing the consideration to the user would it make sense to:

  1. check that s.len() >= len + INPUT_PADDING holds or error
  2. push a ' ' to s.len() to ensure the string is properly terminated

Comment thread tests/fill_tape_padded.rs
Comment on lines +33 to +35
// Spaces, not zeros: a root-level number or atom is terminated by the byte after it,
// and a NUL is not a valid terminator.
scratch.resize(scratch.len() + INPUT_PADDING, b' ');

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Every test pads with b' ', this is not a guarantee / part of the contract as far as I can tell, the suggestion for #SAfety above would resolve this

Comment thread tests/fill_tape_padded.rs
fn invalid_documents_match_fill_tape() {
assert_matches_fill_tape(&[
br#"{"a":"bad\qescape"}"#,
br#"{"a":"\ud83d"}"#, // unpaired surrogate

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This document probably shouldn't pass there is #481 fixing that, we probably shouldn't enshrine a bug in the tests 😅

Comment thread src/impls/native/deser.rs
Comment on lines +25 to +30
let mut b = unsafe { src.add(src_i).read() };

// quickly skip all the "good stuff"
while b != b'"' && b != b'\\' {
src_i += 1;
b = unsafe { *src.get_kinda_unchecked(src_i) };
b = unsafe { src.add(src_i).read() };

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we use get_kinda_unchecked to toggle between 'I trust this' reads in release builds and bounds checks in dev for easier error finding I don't think we should change that

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants