enable atomics and back to optimizing for speed

This commit is contained in:
Toshit Chawda 2024-02-04 12:06:51 -08:00
parent 54011e1f8a
commit 2158b9323e
No known key found for this signature in database
GPG key ID: 91480ED99E2B3D9D
10 changed files with 45 additions and 65 deletions

View file

@ -6,12 +6,8 @@ edition = "2021"
[lib]
crate-type = ["cdylib"]
[features]
default = ["console_error_panic_hook"]
[dependencies]
bytes = "1.5.0"
console_error_panic_hook = { version = "0.1.7", optional = true }
http = "1.0.0"
http-body-util = "0.1.0"
hyper = { version = "1.1.0", features = ["client", "http1"] }
@ -24,19 +20,15 @@ futures-util = "0.3.30"
js-sys = "0.3.66"
webpki-roots = "0.26.0"
tokio-rustls = "0.25.0"
web-sys = { version = "0.3.66", features = ["TextEncoder", "Navigator", "Response", "ResponseInit"] }
web-sys = { version = "0.3.66", features = ["TextEncoder", "Response", "ResponseInit"] }
wasm-streams = "0.4.0"
either = "1.9.0"
tokio-util = { version = "0.7.10", features = ["io"] }
async-compression = { version = "0.4.5", features = ["tokio", "gzip", "brotli"] }
fastwebsockets = { version = "0.6.0", features = ["simdutf8", "unstable-split"] }
rand = "0.8.5"
fastwebsockets = { version = "0.6.0", features = ["unstable-split"] }
base64 = "0.21.7"
wisp-mux = { path = "../wisp", features = ["ws_stream_wasm", "tokio_io"] }
async_io_stream = { version = "0.3.3", features = ["tokio_io"] }
[dependencies.getrandom]
features = ["js"]
getrandom = { version = "0.2.12", features = ["js"] }
[dependencies.ring]
features = ["wasm32_unknown_unknown_js"]

View file

@ -5,18 +5,20 @@ shopt -s inherit_errexit
rm -rf out/ || true
mkdir out/
cargo build --target wasm32-unknown-unknown --release
echo "[ws] built rust"
RUSTFLAGS='-C target-feature=+atomics,+bulk-memory' cargo build --target wasm32-unknown-unknown -Z build-std=panic_abort,std --release
echo "[ws] cargo finished"
wasm-bindgen --weak-refs --target no-modules --no-modules-global epoxy --out-dir out/ ../target/wasm32-unknown-unknown/release/epoxy_client.wasm
echo "[ws] bindgen finished"
echo "[ws] wasm-bindgen finished"
mv out/epoxy_client_bg.wasm out/epoxy_client_unoptimized.wasm
time wasm-opt -Oz --vacuum --dce out/epoxy_client_unoptimized.wasm -o out/epoxy_client_bg.wasm
echo "[ws] optimized"
time wasm-opt -O4 --vacuum --dce --enable-threads --enable-bulk-memory --enable-simd out/epoxy_client_unoptimized.wasm -o out/epoxy_client_bg.wasm
echo "[ws] wasm-opt finished"
AUTOGENERATED_SOURCE=$(<"out/epoxy_client.js")
# patch for websocket sharedarraybuffer error
AUTOGENERATED_SOURCE=${AUTOGENERATED_SOURCE//getObject(arg0).send(getArrayU8FromWasm0(arg1, arg2)/getObject(arg0).send(new Uint8Array(getArrayU8FromWasm0(arg1, arg2))}
WASM_BASE64=$(base64 -w0 out/epoxy_client_bg.wasm)
AUTOGENERATED_SOURCE=${AUTOGENERATED_SOURCE//__wbg_init(input) \{/__wbg_init() \{let input=\'data:application/wasm;base64,$WASM_BASE64\'}
AUTOGENERATED_SOURCE=${AUTOGENERATED_SOURCE//__wbg_init(input, maybe_memory) \{/__wbg_init(input, maybe_memory) \{$'\n'if (!input) \{input=\'data:application/wasm;base64,$WASM_BASE64\'\}}
AUTOGENERATED_SOURCE=${AUTOGENERATED_SOURCE//return __wbg_finalize_init\(instance\, module\);/__wbg_finalize_init\(instance\, module\); return epoxy}
echo "$AUTOGENERATED_SOURCE" > epoxy-bundled.js
cp epoxy-bundled.js epoxy-module-bundled.js

View file

@ -111,11 +111,6 @@ async fn send_req(
}
}
#[wasm_bindgen(start)]
async fn start() {
utils::set_panic_hook();
}
#[wasm_bindgen]
pub struct EpoxyClient {
rustls_config: Arc<rustls::ClientConfig>,

View file

@ -4,11 +4,6 @@ use hyper::{header::HeaderValue, Uri};
use http::uri;
use js_sys::{Array, Object};
pub fn set_panic_hook() {
#[cfg(feature = "console_error_panic_hook")]
console_error_panic_hook::set_once();
}
#[wasm_bindgen]
extern "C" {
#[wasm_bindgen(js_namespace = console, js_name = debug)]
@ -55,15 +50,15 @@ pub trait ReplaceErr {
fn replace_err_jv(self, err: &str) -> Result<Self::Ok, JsValue>;
}
impl<T, E> ReplaceErr for Result<T, E> {
impl<T, E: std::fmt::Debug> ReplaceErr for Result<T, E> {
type Ok = T;
fn replace_err(self, err: &str) -> Result<<Self as ReplaceErr>::Ok, JsError> {
self.map_err(|_| jerr!(err))
self.map_err(|oe| jerr!(&format!("{}, original error: {:?}", err, oe)))
}
fn replace_err_jv(self, err: &str) -> Result<<Self as ReplaceErr>::Ok, JsValue> {
self.map_err(|_| jval!(err))
self.map_err(|oe| jval!(&format!("{}, original error: {:?}", err, oe)))
}
}

View file

@ -4,6 +4,7 @@ use base64::{engine::general_purpose::STANDARD, Engine};
use fastwebsockets::{
CloseCode, FragmentCollectorRead, Frame, OpCode, Payload, Role, WebSocket, WebSocketWrite,
};
use futures_util::lock::Mutex;
use http_body_util::Empty;
use hyper::{
header::{CONNECTION, UPGRADE},
@ -16,7 +17,7 @@ use tokio::io::WriteHalf;
#[wasm_bindgen]
pub struct EpxWebSocket {
tx: WebSocketWrite<WriteHalf<TokioIo<Upgraded>>>,
tx: Arc<Mutex<WebSocketWrite<WriteHalf<TokioIo<Upgraded>>>>>,
onerror: Function,
}
@ -44,7 +45,8 @@ impl EpxWebSocket {
let url = Uri::try_from(url).replace_err("Failed to parse URL")?;
let host = url.host().replace_err("URL must have a host")?;
let rand: [u8; 16] = rand::random();
let mut rand: [u8; 16] = [0; 16];
getrandom::getrandom(&mut rand)?;
let key = STANDARD.encode(rand);
let mut builder = Request::builder()
@ -88,16 +90,12 @@ impl EpxWebSocket {
let (rx, tx) = ws.split(tokio::io::split);
let mut rx = FragmentCollectorRead::new(rx);
let tx = Arc::new(Mutex::new(tx));
let tx_cloned = tx.clone();
wasm_bindgen_futures::spawn_local(async move {
while let Ok(frame) = rx
.read_frame(&mut |arg| async move {
error!(
"wtf is an obligated write {:?}, {:?}, {:?}",
arg.fin, arg.opcode, arg.payload
);
Ok::<(), std::io::Error>(())
})
.read_frame(&mut |arg| async { tx_cloned.lock().await.write_frame(arg).await })
.await
{
match frame.opcode {
@ -137,10 +135,12 @@ impl EpxWebSocket {
}
#[wasm_bindgen]
pub async fn send(&mut self, payload: String) -> Result<(), JsError> {
pub async fn send(&self, payload: String) -> Result<(), JsError> {
let onerr = self.onerror.clone();
let ret = self
.tx
.lock()
.await
.write_frame(Frame::text(Payload::Owned(payload.as_bytes().to_vec())))
.await;
if let Err(ret) = ret {
@ -152,8 +152,10 @@ impl EpxWebSocket {
}
#[wasm_bindgen]
pub async fn close(&mut self) -> Result<(), JsError> {
pub async fn close(&self) -> Result<(), JsError> {
self.tx
.lock()
.await
.write_frame(Frame::close(CloseCode::Normal.into(), b""))
.await?;
Ok(())