perf: reduce memcpy call in HTML escaping
This commit is contained in:
parent
36281a7da6
commit
f236a98fed
|
@ -8,6 +8,7 @@ use std::slice;
|
||||||
|
|
||||||
use super::super::Buffer;
|
use super::super::Buffer;
|
||||||
use super::{ESCAPED, ESCAPED_LEN, ESCAPE_LUT};
|
use super::{ESCAPED, ESCAPED_LEN, ESCAPE_LUT};
|
||||||
|
use super::naive::push_escaped_str;
|
||||||
|
|
||||||
const VECTOR_BYTES: usize = std::mem::size_of::<__m256i>();
|
const VECTOR_BYTES: usize = std::mem::size_of::<__m256i>();
|
||||||
|
|
||||||
|
@ -41,6 +42,7 @@ pub unsafe fn escape(feed: &str, buffer: &mut Buffer) {
|
||||||
let mut mask = maskgen(_mm256_loadu_si256(ptr as *const __m256i));
|
let mut mask = maskgen(_mm256_loadu_si256(ptr as *const __m256i));
|
||||||
while mask != 0 {
|
while mask != 0 {
|
||||||
let trailing_zeros = mask.trailing_zeros() as usize;
|
let trailing_zeros = mask.trailing_zeros() as usize;
|
||||||
|
mask ^= 1 << trailing_zeros;
|
||||||
let ptr2 = ptr.add(trailing_zeros);
|
let ptr2 = ptr.add(trailing_zeros);
|
||||||
let c = ESCAPE_LUT[*ptr2 as usize] as usize;
|
let c = ESCAPE_LUT[*ptr2 as usize] as usize;
|
||||||
if c < ESCAPED_LEN {
|
if c < ESCAPED_LEN {
|
||||||
|
@ -51,10 +53,9 @@ pub unsafe fn escape(feed: &str, buffer: &mut Buffer) {
|
||||||
);
|
);
|
||||||
buffer.push_str(std::str::from_utf8_unchecked(slc));
|
buffer.push_str(std::str::from_utf8_unchecked(slc));
|
||||||
}
|
}
|
||||||
buffer.push_str(*ESCAPED.get_unchecked(c));
|
push_escaped_str(*ESCAPED.get_unchecked(c), buffer);
|
||||||
start_ptr = ptr2.add(1);
|
start_ptr = ptr2.add(1);
|
||||||
}
|
}
|
||||||
mask ^= 1 << trailing_zeros;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ptr = ptr.add(VECTOR_BYTES);
|
ptr = ptr.add(VECTOR_BYTES);
|
||||||
|
@ -70,6 +71,7 @@ pub unsafe fn escape(feed: &str, buffer: &mut Buffer) {
|
||||||
maskgen(_mm256_loadu_si256(ptr.sub(backs) as *const __m256i)) >> backs;
|
maskgen(_mm256_loadu_si256(ptr.sub(backs) as *const __m256i)) >> backs;
|
||||||
while mask != 0 {
|
while mask != 0 {
|
||||||
let trailing_zeros = mask.trailing_zeros() as usize;
|
let trailing_zeros = mask.trailing_zeros() as usize;
|
||||||
|
mask ^= 1 << trailing_zeros;
|
||||||
let ptr2 = ptr.add(trailing_zeros);
|
let ptr2 = ptr.add(trailing_zeros);
|
||||||
let c = ESCAPE_LUT[*ptr2 as usize] as usize;
|
let c = ESCAPE_LUT[*ptr2 as usize] as usize;
|
||||||
if c < ESCAPED_LEN {
|
if c < ESCAPED_LEN {
|
||||||
|
@ -80,10 +82,9 @@ pub unsafe fn escape(feed: &str, buffer: &mut Buffer) {
|
||||||
);
|
);
|
||||||
buffer.push_str(std::str::from_utf8_unchecked(slc));
|
buffer.push_str(std::str::from_utf8_unchecked(slc));
|
||||||
}
|
}
|
||||||
buffer.push_str(*ESCAPED.get_unchecked(c));
|
push_escaped_str(*ESCAPED.get_unchecked(c), buffer);
|
||||||
start_ptr = ptr2.add(1);
|
start_ptr = ptr2.add(1);
|
||||||
}
|
}
|
||||||
mask ^= 1 << trailing_zeros;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -119,6 +120,7 @@ unsafe fn escape_small(feed: &str, buffer: &mut Buffer) {
|
||||||
let mut mask = maskgen(_mm_loadu_si128(ptr as *const __m128i));
|
let mut mask = maskgen(_mm_loadu_si128(ptr as *const __m128i));
|
||||||
while mask != 0 {
|
while mask != 0 {
|
||||||
let trailing_zeros = mask.trailing_zeros() as usize;
|
let trailing_zeros = mask.trailing_zeros() as usize;
|
||||||
|
mask ^= 1 << trailing_zeros;
|
||||||
let ptr2 = ptr.add(trailing_zeros);
|
let ptr2 = ptr.add(trailing_zeros);
|
||||||
let c = ESCAPE_LUT[*ptr2 as usize] as usize;
|
let c = ESCAPE_LUT[*ptr2 as usize] as usize;
|
||||||
if c < ESCAPED_LEN {
|
if c < ESCAPED_LEN {
|
||||||
|
@ -127,10 +129,9 @@ unsafe fn escape_small(feed: &str, buffer: &mut Buffer) {
|
||||||
slice::from_raw_parts(start_ptr, ptr2 as usize - start_ptr as usize);
|
slice::from_raw_parts(start_ptr, ptr2 as usize - start_ptr as usize);
|
||||||
buffer.push_str(std::str::from_utf8_unchecked(slc));
|
buffer.push_str(std::str::from_utf8_unchecked(slc));
|
||||||
}
|
}
|
||||||
buffer.push_str(*ESCAPED.get_unchecked(c));
|
push_escaped_str(*ESCAPED.get_unchecked(c), buffer);
|
||||||
start_ptr = ptr2.add(1);
|
start_ptr = ptr2.add(1);
|
||||||
}
|
}
|
||||||
mask ^= 1 << trailing_zeros;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if len != 16 {
|
if len != 16 {
|
||||||
|
@ -141,6 +142,7 @@ unsafe fn escape_small(feed: &str, buffer: &mut Buffer) {
|
||||||
|
|
||||||
while mask != 0 {
|
while mask != 0 {
|
||||||
let trailing_zeros = mask.trailing_zeros() as usize;
|
let trailing_zeros = mask.trailing_zeros() as usize;
|
||||||
|
mask ^= 1 << trailing_zeros;
|
||||||
let ptr2 = ptr.add(trailing_zeros);
|
let ptr2 = ptr.add(trailing_zeros);
|
||||||
let c = ESCAPE_LUT[*ptr2 as usize] as usize;
|
let c = ESCAPE_LUT[*ptr2 as usize] as usize;
|
||||||
if c < ESCAPED_LEN {
|
if c < ESCAPED_LEN {
|
||||||
|
@ -151,10 +153,9 @@ unsafe fn escape_small(feed: &str, buffer: &mut Buffer) {
|
||||||
);
|
);
|
||||||
buffer.push_str(std::str::from_utf8_unchecked(slc));
|
buffer.push_str(std::str::from_utf8_unchecked(slc));
|
||||||
}
|
}
|
||||||
buffer.push_str(*ESCAPED.get_unchecked(c));
|
push_escaped_str(*ESCAPED.get_unchecked(c), buffer);
|
||||||
start_ptr = ptr2.add(1);
|
start_ptr = ptr2.add(1);
|
||||||
}
|
}
|
||||||
mask ^= 1 << trailing_zeros;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
use core::slice;
|
use std::ptr;
|
||||||
|
use std::slice;
|
||||||
|
|
||||||
use super::super::utils::memcpy_16;
|
use super::super::utils::memcpy_16;
|
||||||
use super::super::Buffer;
|
use super::super::Buffer;
|
||||||
|
@ -38,7 +39,7 @@ pub(super) unsafe fn proceed(
|
||||||
slice::from_raw_parts(start_ptr, ptr as usize - start_ptr as usize);
|
slice::from_raw_parts(start_ptr, ptr as usize - start_ptr as usize);
|
||||||
buffer.push_str(std::str::from_utf8_unchecked(slc));
|
buffer.push_str(std::str::from_utf8_unchecked(slc));
|
||||||
}
|
}
|
||||||
buffer.push_str(*ESCAPED.get_unchecked(idx));
|
push_escaped_str(*ESCAPED.get_unchecked(idx), buffer);
|
||||||
start_ptr = ptr.add(1);
|
start_ptr = ptr.add(1);
|
||||||
ptr = ptr.add(1);
|
ptr = ptr.add(1);
|
||||||
}
|
}
|
||||||
|
@ -87,3 +88,20 @@ pub(super) unsafe fn escape_small(feed: &str, mut buf: *mut u8) -> usize {
|
||||||
|
|
||||||
buf as usize - buf_begin as usize
|
buf as usize - buf_begin as usize
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub(super) unsafe fn push_escaped_str(value: &str, buffer: &mut Buffer) {
|
||||||
|
buffer.reserve_small(value.len());
|
||||||
|
|
||||||
|
let src = value.as_ptr();
|
||||||
|
let dst = buffer.as_mut_ptr().add(buffer.len());
|
||||||
|
|
||||||
|
// memcpy
|
||||||
|
let offset = value.len() - 4;
|
||||||
|
let t2 = ptr::read_unaligned(src.add(offset) as *const u32);
|
||||||
|
let t1 = ptr::read_unaligned(src as *const u32);
|
||||||
|
ptr::write_unaligned(dst.add(offset) as *mut u32, t2);
|
||||||
|
ptr::write_unaligned(dst as *mut u32, t1);
|
||||||
|
|
||||||
|
buffer._set_len(buffer.len() + value.len());
|
||||||
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@ use std::slice;
|
||||||
|
|
||||||
use super::super::Buffer;
|
use super::super::Buffer;
|
||||||
use super::{ESCAPED, ESCAPED_LEN, ESCAPE_LUT};
|
use super::{ESCAPED, ESCAPED_LEN, ESCAPE_LUT};
|
||||||
|
use super::naive::push_escaped_str;
|
||||||
|
|
||||||
const VECTOR_BYTES: usize = std::mem::size_of::<__m128i>();
|
const VECTOR_BYTES: usize = std::mem::size_of::<__m128i>();
|
||||||
|
|
||||||
|
@ -34,6 +35,7 @@ pub unsafe fn escape(feed: &str, buffer: &mut Buffer) {
|
||||||
let mut mask = maskgen(_mm_loadu_si128(ptr as *const __m128i));
|
let mut mask = maskgen(_mm_loadu_si128(ptr as *const __m128i));
|
||||||
while mask != 0 {
|
while mask != 0 {
|
||||||
let trailing_zeros = mask.trailing_zeros() as usize;
|
let trailing_zeros = mask.trailing_zeros() as usize;
|
||||||
|
mask ^= 1 << trailing_zeros;
|
||||||
let ptr2 = ptr.add(trailing_zeros);
|
let ptr2 = ptr.add(trailing_zeros);
|
||||||
let c = ESCAPE_LUT[*ptr2 as usize] as usize;
|
let c = ESCAPE_LUT[*ptr2 as usize] as usize;
|
||||||
if c < ESCAPED_LEN {
|
if c < ESCAPED_LEN {
|
||||||
|
@ -44,10 +46,9 @@ pub unsafe fn escape(feed: &str, buffer: &mut Buffer) {
|
||||||
);
|
);
|
||||||
buffer.push_str(std::str::from_utf8_unchecked(slc));
|
buffer.push_str(std::str::from_utf8_unchecked(slc));
|
||||||
}
|
}
|
||||||
buffer.push_str(*ESCAPED.get_unchecked(c));
|
push_escaped_str(*ESCAPED.get_unchecked(c), buffer);
|
||||||
start_ptr = ptr2.add(1);
|
start_ptr = ptr2.add(1);
|
||||||
}
|
}
|
||||||
mask ^= 1 << trailing_zeros;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ptr = ptr.add(VECTOR_BYTES);
|
ptr = ptr.add(VECTOR_BYTES);
|
||||||
|
@ -63,6 +64,7 @@ pub unsafe fn escape(feed: &str, buffer: &mut Buffer) {
|
||||||
let mut mask = maskgen(_mm_loadu_si128(read_ptr as *const __m128i)) >> backs;
|
let mut mask = maskgen(_mm_loadu_si128(read_ptr as *const __m128i)) >> backs;
|
||||||
while mask != 0 {
|
while mask != 0 {
|
||||||
let trailing_zeros = mask.trailing_zeros() as usize;
|
let trailing_zeros = mask.trailing_zeros() as usize;
|
||||||
|
mask ^= 1 << trailing_zeros;
|
||||||
let ptr2 = ptr.add(trailing_zeros);
|
let ptr2 = ptr.add(trailing_zeros);
|
||||||
let c = ESCAPE_LUT[*ptr2 as usize] as usize;
|
let c = ESCAPE_LUT[*ptr2 as usize] as usize;
|
||||||
if c < ESCAPED_LEN {
|
if c < ESCAPED_LEN {
|
||||||
|
@ -73,10 +75,9 @@ pub unsafe fn escape(feed: &str, buffer: &mut Buffer) {
|
||||||
);
|
);
|
||||||
buffer.push_str(std::str::from_utf8_unchecked(slc));
|
buffer.push_str(std::str::from_utf8_unchecked(slc));
|
||||||
}
|
}
|
||||||
buffer.push_str(*ESCAPED.get_unchecked(c));
|
push_escaped_str(*ESCAPED.get_unchecked(c), buffer);
|
||||||
start_ptr = ptr2.add(1);
|
start_ptr = ptr2.add(1);
|
||||||
}
|
}
|
||||||
mask ^= 1 << trailing_zeros;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue