From 9a7f62e3ca91d18177dc7b27a919aaa128f14971 Mon Sep 17 00:00:00 2001 From: Kogia-sima Date: Thu, 18 Jun 2020 16:32:07 +0900 Subject: [PATCH] Improve buffering performance --- Cargo.lock | 7 ++++++ sailfish/Cargo.toml | 3 +++ sailfish/build.rs | 5 +++++ sailfish/src/lib.rs | 1 + sailfish/src/runtime/buffer.rs | 41 +++++++++++++++++++++++----------- sailfish/src/runtime/mod.rs | 17 ++++++++++++++ 6 files changed, 61 insertions(+), 13 deletions(-) create mode 100644 sailfish/build.rs diff --git a/Cargo.lock b/Cargo.lock index 86e7ae6..35db958 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -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" diff --git a/sailfish/Cargo.toml b/sailfish/Cargo.toml index b5015b4..c80c332 100644 --- a/sailfish/Cargo.toml +++ b/sailfish/Cargo.toml @@ -14,3 +14,6 @@ edition = "2018" [dependencies] ryu = "1.0.4" + +[build-dependencies] +version_check = "0.9.2" diff --git a/sailfish/build.rs b/sailfish/build.rs new file mode 100644 index 0000000..65cc907 --- /dev/null +++ b/sailfish/build.rs @@ -0,0 +1,5 @@ +fn main() { + if version_check::is_feature_flaggable() == Some(true) { + println!("cargo:rustc-cfg=sailfish_nightly"); + } +} diff --git a/sailfish/src/lib.rs b/sailfish/src/lib.rs index e95c423..aa24433 100644 --- a/sailfish/src/lib.rs +++ b/sailfish/src/lib.rs @@ -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; diff --git a/sailfish/src/runtime/buffer.rs b/sailfish/src/runtime/buffer.rs index 9d6253f..02a2402 100644 --- a/sailfish/src/runtime/buffer.rs +++ b/sailfish/src/runtime/buffer.rs @@ -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 } } diff --git a/sailfish/src/runtime/mod.rs b/sailfish/src/runtime/mod.rs index 0e3c161..0232380 100644 --- a/sailfish/src/runtime/mod.rs +++ b/sailfish/src/runtime/mod.rs @@ -55,3 +55,20 @@ impl Context { Ok(self.buf.into_string()) } } + +// #[inline(never)] +// pub fn _instantiate(table: Vec>) -> String { +// let mut buffer = Buffer::with_capacity(130000); +// buffer.push_str(""); +// for r1 in table { +// buffer.push_str(""); +// } +// buffer.push_str("
"); +// for r2 in r1 { +// let _ = (&r2).render(&mut buffer); +// buffer.push_str(""); +// } +// unsafe { buffer.set_len(buffer.len() - 4) } +// buffer.push_str("
"); +// buffer.into_string() +// }