Improve buffering performance
This commit is contained in:
parent
48eb36560a
commit
9a7f62e3ca
|
@ -1043,6 +1043,7 @@ name = "sailfish"
|
|||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"ryu 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"version_check 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1347,6 +1348,11 @@ dependencies = [
|
|||
"percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "version_check"
|
||||
version = "0.9.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.9.0+wasi-snapshot-preview1"
|
||||
|
@ -1561,6 +1567,7 @@ dependencies = [
|
|||
"checksum unicode-segmentation 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e83e153d1053cbb5a118eeff7fd5be06ed99153f00dbcd8ae310c5fb2b22edc0"
|
||||
"checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c"
|
||||
"checksum url 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "829d4a8476c35c9bf0bbce5a3b23f4106f79728039b726d292bb93bc106787cb"
|
||||
"checksum version_check 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed"
|
||||
"checksum wasi 0.9.0+wasi-snapshot-preview1 (registry+https://github.com/rust-lang/crates.io-index)" = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519"
|
||||
"checksum widestring 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "effc0e4ff8085673ea7b9b2e3c73f6bd4d118810c9009ed8f1e16bd96c331db6"
|
||||
"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
|
||||
|
|
|
@ -14,3 +14,6 @@ edition = "2018"
|
|||
|
||||
[dependencies]
|
||||
ryu = "1.0.4"
|
||||
|
||||
[build-dependencies]
|
||||
version_check = "0.9.2"
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
fn main() {
|
||||
if version_check::is_feature_flaggable() == Some(true) {
|
||||
println!("cargo:rustc-cfg=sailfish_nightly");
|
||||
}
|
||||
}
|
|
@ -34,6 +34,7 @@
|
|||
#![doc(
|
||||
html_logo_url = "https://raw.githubusercontent.com/Kogia-sima/sailfish/master/resources/icon.png"
|
||||
)]
|
||||
#![cfg_attr(sailfish_nightly, feature(core_intrinsics))]
|
||||
|
||||
pub mod runtime;
|
||||
|
||||
|
|
|
@ -4,6 +4,20 @@ use std::mem::{align_of, ManuallyDrop};
|
|||
use std::ops::{Add, AddAssign};
|
||||
use std::ptr;
|
||||
|
||||
#[cfg(sailfish_nightly)]
|
||||
macro_rules! unlikely {
|
||||
($val:expr) => {
|
||||
std::intrinsics::unlikely($val)
|
||||
};
|
||||
}
|
||||
|
||||
#[cfg(not(sailfish_nightly))]
|
||||
macro_rules! unlikely {
|
||||
($val:expr) => {
|
||||
$val
|
||||
};
|
||||
}
|
||||
|
||||
/// Buffer for rendered contents
|
||||
///
|
||||
/// This struct is quite simular to `String`, but some methods are
|
||||
|
@ -86,7 +100,7 @@ impl Buffer {
|
|||
|
||||
#[inline]
|
||||
pub fn reserve(&mut self, size: usize) {
|
||||
if size > self.capacity - self.len {
|
||||
if unlikely!(self.len + size > self.capacity) {
|
||||
self.reserve_internal(size);
|
||||
}
|
||||
}
|
||||
|
@ -105,9 +119,7 @@ impl Buffer {
|
|||
#[inline]
|
||||
pub fn push_str(&mut self, data: &str) {
|
||||
let size = data.len();
|
||||
if size > self.capacity - self.len {
|
||||
self.reserve_internal(size);
|
||||
}
|
||||
self.reserve(size);
|
||||
unsafe {
|
||||
let p = self.data.add(self.len);
|
||||
std::ptr::copy_nonoverlapping(data.as_ptr(), p, size);
|
||||
|
@ -121,28 +133,31 @@ impl Buffer {
|
|||
self.push_str(data.encode_utf8(&mut buf));
|
||||
}
|
||||
|
||||
#[inline(never)]
|
||||
#[inline]
|
||||
fn reserve_internal(&mut self, size: usize) {
|
||||
unsafe {
|
||||
let new_capacity = std::cmp::max(self.capacity * 2, self.len + size);
|
||||
self.realloc(new_capacity);
|
||||
self.data = self.realloc(new_capacity);
|
||||
self.capacity = new_capacity;
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn realloc(&mut self, cap: usize) {
|
||||
if self.capacity == 0 {
|
||||
#[inline]
|
||||
unsafe fn realloc(&self, cap: usize) -> *mut u8 {
|
||||
let data = if unlikely!(self.capacity == 0) {
|
||||
let new_layout = Layout::from_size_align_unchecked(cap, 1);
|
||||
self.data = alloc(new_layout);
|
||||
alloc(new_layout)
|
||||
} else {
|
||||
assert!(cap <= std::usize::MAX / 2, "capacity is too large");
|
||||
debug_assert!(cap <= std::usize::MAX / 2, "capacity is too large");
|
||||
let old_layout = Layout::from_size_align_unchecked(self.capacity, 1);
|
||||
self.data = realloc(self.data, old_layout, cap);
|
||||
}
|
||||
realloc(self.data, old_layout, cap)
|
||||
};
|
||||
|
||||
if self.data.is_null() {
|
||||
if data.is_null() {
|
||||
handle_alloc_error(Layout::from_size_align_unchecked(cap, 1));
|
||||
}
|
||||
|
||||
data
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -55,3 +55,20 @@ impl Context {
|
|||
Ok(self.buf.into_string())
|
||||
}
|
||||
}
|
||||
|
||||
// #[inline(never)]
|
||||
// pub fn _instantiate(table: Vec<Vec<usize>>) -> String {
|
||||
// let mut buffer = Buffer::with_capacity(130000);
|
||||
// buffer.push_str("<table>");
|
||||
// for r1 in table {
|
||||
// buffer.push_str("<tr><td>");
|
||||
// for r2 in r1 {
|
||||
// let _ = (&r2).render(&mut buffer);
|
||||
// buffer.push_str("</td><td>");
|
||||
// }
|
||||
// unsafe { buffer.set_len(buffer.len() - 4) }
|
||||
// buffer.push_str("</tr>");
|
||||
// }
|
||||
// buffer.push_str("</table>");
|
||||
// buffer.into_string()
|
||||
// }
|
||||
|
|
Loading…
Reference in New Issue