From 2158b9323edc90320734344ef8e352b485ad9f6c Mon Sep 17 00:00:00 2001 From: Toshit Chawda Date: Sun, 4 Feb 2024 12:06:51 -0800 Subject: [PATCH] enable atomics and back to optimizing for speed --- Cargo.lock | 24 +++--------------------- Cargo.toml | 2 +- client/Cargo.toml | 14 +++----------- client/build.sh | 14 ++++++++------ client/src/lib.rs | 5 ----- client/src/utils.rs | 11 +++-------- client/src/websocket.rs | 24 +++++++++++++----------- server/src/main.rs | 2 ++ simple-wisp-client/Cargo.toml | 1 + simple-wisp-client/src/main.rs | 13 +++++++++++-- 10 files changed, 45 insertions(+), 65 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0d1f3d3..40758a6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -154,16 +154,6 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" -[[package]] -name = "console_error_panic_hook" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc" -dependencies = [ - "cfg-if", - "wasm-bindgen", -] - [[package]] name = "core-foundation" version = "0.9.4" @@ -231,12 +221,6 @@ dependencies = [ "crypto-common", ] -[[package]] -name = "either" -version = "1.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" - [[package]] name = "epoxy-client" version = "1.0.0" @@ -245,8 +229,6 @@ dependencies = [ "async_io_stream", "base64", "bytes", - "console_error_panic_hook", - "either", "fastwebsockets", "futures-util", "getrandom", @@ -255,7 +237,6 @@ dependencies = [ "hyper", "js-sys", "pin-project-lite", - "rand", "ring", "tokio", "tokio-rustls", @@ -453,9 +434,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.11" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe9006bed769170c11f845cf00c7c1e9092aeb3f268e007c3e760ac68008070f" +checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" dependencies = [ "cfg-if", "js-sys", @@ -1023,6 +1004,7 @@ dependencies = [ "hyper", "tokio", "tokio-native-tls", + "tokio-util", "wisp-mux", ] diff --git a/Cargo.toml b/Cargo.toml index 2fcf5e1..2e8971b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,5 +7,5 @@ rustls-pki-types = { git = "https://github.com/r58Playz/rustls-pki-types" } [profile.release] lto = true -opt-level = 'z' +opt-level = 3 codegen-units = 1 diff --git a/client/Cargo.toml b/client/Cargo.toml index 48ff0e5..3f8efd3 100644 --- a/client/Cargo.toml +++ b/client/Cargo.toml @@ -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"] diff --git a/client/build.sh b/client/build.sh index 9d5a889..7c2725b 100755 --- a/client/build.sh +++ b/client/build.sh @@ -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 diff --git a/client/src/lib.rs b/client/src/lib.rs index afd7b20..639c786 100644 --- a/client/src/lib.rs +++ b/client/src/lib.rs @@ -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, diff --git a/client/src/utils.rs b/client/src/utils.rs index 077a120..caf4498 100644 --- a/client/src/utils.rs +++ b/client/src/utils.rs @@ -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; } -impl ReplaceErr for Result { +impl ReplaceErr for Result { type Ok = T; fn replace_err(self, err: &str) -> Result<::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<::Ok, JsValue> { - self.map_err(|_| jval!(err)) + self.map_err(|oe| jval!(&format!("{}, original error: {:?}", err, oe))) } } diff --git a/client/src/websocket.rs b/client/src/websocket.rs index a83b755..f823077 100644 --- a/client/src/websocket.rs +++ b/client/src/websocket.rs @@ -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>>, + tx: Arc>>>>, 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(()) diff --git a/server/src/main.rs b/server/src/main.rs index aeca64e..04c39e7 100644 --- a/server/src/main.rs +++ b/server/src/main.rs @@ -78,6 +78,8 @@ async fn accept_http( let uri = req.uri().clone(); let (mut res, fut) = upgrade::upgrade(&mut req)?; + println!("{:?} {:?}", uri.path(), prefix); + if *uri.path() != prefix { tokio::spawn(async move { accept_wsproxy(fut, uri.path().strip_prefix(&prefix).unwrap(), addr.clone()).await diff --git a/simple-wisp-client/Cargo.toml b/simple-wisp-client/Cargo.toml index 972d5da..9525805 100644 --- a/simple-wisp-client/Cargo.toml +++ b/simple-wisp-client/Cargo.toml @@ -11,5 +11,6 @@ http-body-util = "0.1.0" hyper = { version = "1.1.0", features = ["http1", "client"] } tokio = { version = "1.36.0", features = ["full"] } tokio-native-tls = "0.3.1" +tokio-util = "0.7.10" wisp-mux = { path = "../wisp", features = ["fastwebsockets"]} diff --git a/simple-wisp-client/src/main.rs b/simple-wisp-client/src/main.rs index db49784..b530f64 100644 --- a/simple-wisp-client/src/main.rs +++ b/simple-wisp-client/src/main.rs @@ -10,6 +10,7 @@ use std::{error::Error, future::Future}; use tokio::net::TcpStream; use tokio_native_tls::{native_tls, TlsConnector}; use wisp_mux::{ClientMux, StreamType}; +use tokio_util::either::Either; #[derive(Debug)] struct StrError(String); @@ -59,10 +60,18 @@ async fn main() -> Result<(), Box> { .nth(4) .ok_or(StrError::new("no dest port"))? .parse()?; + let should_tls: bool = std::env::args() + .nth(5) + .ok_or(StrError::new("no should tls"))? + .parse()?; let socket = TcpStream::connect(format!("{}:{}", &addr, addr_port)).await?; - let cx = TlsConnector::from(native_tls::TlsConnector::builder().build()?); - let socket = cx.connect(&addr, socket).await?; + let socket = if should_tls { + let cx = TlsConnector::from(native_tls::TlsConnector::builder().build()?); + Either::Left(cx.connect(&addr, socket).await?) + } else { + Either::Right(socket) + }; let req = Request::builder() .method("GET") .uri(format!("wss://{}:{}/", &addr, addr_port))