From 3817f271a26aeafe607a458dfce383ffa8f3c3e7 Mon Sep 17 00:00:00 2001 From: Piotr Sikora Date: Tue, 15 Mar 2022 11:13:32 -0700 Subject: [PATCH 1/4] Add proxy_wasm::main macro. This is primarly a mechanism to deliver a workaround for a breaking change in Rust v1.56.0 (which updated LLVM to v13.0), which changed existing reactors into multi-entry commands, leading to performance degradation and/or unusable Proxy-Wasm plugins. See: https://github.com/WebAssembly/WASI/issues/471 This is delivered as a macro to make it somehow compatible with the unstable "-Z wasi-exec-model=reactor" feature. Signed-off-by: Piotr Sikora --- .github/workflows/rust.yml | 35 +++++++++++++++++++++++++++++++++++ BUILD | 10 ++++++++++ CHANGELOG.md | 2 ++ Cargo.toml | 1 + build.rs | 29 +++++++++++++++++++++++++++++ examples/hello_world.rs | 5 ++--- examples/http_auth_random.rs | 5 ++--- examples/http_body.rs | 5 ++--- examples/http_config.rs | 5 ++--- examples/http_headers.rs | 5 ++--- src/lib.rs | 34 ++++++++++++++++++++++++++++++++++ 11 files changed, 121 insertions(+), 15 deletions(-) create mode 100644 build.rs diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index c0f9b47f..4ba91618 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -195,6 +195,41 @@ jobs: - name: Package (publish) run: cargo publish --dry-run --target=wasm32-unknown-unknown + reactor: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + + - name: Update Rust + run: | + rustup toolchain install nightly --component clippy + rustup +nightly target add wasm32-wasi + rustup default nightly + + - name: Rewrite Cargo.toml examples + run: grep -v '^crate-type' Cargo.toml > Cargo.tmp && mv Cargo.tmp Cargo.toml + + - name: Build (wasm32-wasi) + env: + RUSTFLAGS: -D warnings -C link-args=-S -Z wasi-exec-model=reactor + run: cargo build --release --all-targets --target=wasm32-wasi + + - name: Build (wasm32-wasi with wee-alloc) + env: + RUSTFLAGS: -D warnings -C link-args=-S -Z wasi-exec-model=reactor + run: cargo build --release --all-targets --target=wasm32-wasi --features=wee-alloc + + - name: Clippy (wasm32-wasi) + env: + RUSTFLAGS: -D warnings -C link-args=-S -Z wasi-exec-model=reactor + run: cargo clippy --release --all-targets --target=wasm32-wasi + + - name: Clippy (wasm32-wasi with wee-alloc) + env: + RUSTFLAGS: -D warnings -C link-args=-S -Z wasi-exec-model=reactor + run: cargo clippy --release --all-targets --target=wasm32-wasi --features=wee-alloc + outdated: runs-on: ubuntu-latest diff --git a/BUILD b/BUILD index 6d5f6672..1de8787b 100644 --- a/BUILD +++ b/BUILD @@ -1,11 +1,21 @@ +load("@rules_rust//cargo:cargo_build_script.bzl", "cargo_build_script") load("@rules_rust//rust:defs.bzl", "rust_library") +cargo_build_script( + name = "proxy_wasm_build_script", + srcs = ["build.rs"], + edition = "2018", + tags = ["manual"], + visibility = ["//visibility:private"], +) + rust_library( name = "proxy_wasm", srcs = glob(["src/*.rs"]), edition = "2018", visibility = ["//visibility:public"], deps = [ + ":proxy_wasm_build_script", "//bazel/cargo:hashbrown", "//bazel/cargo:log", ], diff --git a/CHANGELOG.md b/CHANGELOG.md index f3516cf6..50ac6191 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ### Changed +- Added `proxy_wasm::main` macro that should be used instead of custom `_start`, + `_initialize` and/or `main` exports. - Updated ABI to Proxy-Wasm ABI v0.2.1. ## [0.1.4] - 2021-07-01 diff --git a/Cargo.toml b/Cargo.toml index 22eebd9b..102bf533 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,6 +7,7 @@ readme = "README.md" license = "Apache-2.0" repository = "https://github.com/proxy-wasm/proxy-wasm-rust-sdk" edition = "2018" +build = "build.rs" [features] wee-alloc = ["wee_alloc"] diff --git a/build.rs b/build.rs new file mode 100644 index 00000000..2d668733 --- /dev/null +++ b/build.rs @@ -0,0 +1,29 @@ +// Copyright 2022 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +fn main() { + if let Some(target_os) = std::env::var_os("CARGO_CFG_TARGET_OS") { + if target_os != "wasi" { + return; + } + } + if let Some(rustflags) = std::env::var_os("CARGO_ENCODED_RUSTFLAGS") { + for flag in rustflags.to_string_lossy().split('\x1f') { + if flag.ends_with("wasi-exec-model=reactor") { + println!("cargo:rustc-cfg=wasi_exec_model_reactor"); + return; + } + } + } +} diff --git a/examples/hello_world.rs b/examples/hello_world.rs index b493aa1b..7eb1cc64 100644 --- a/examples/hello_world.rs +++ b/examples/hello_world.rs @@ -22,11 +22,10 @@ use std::time::Duration; #[cfg(not(all(target_arch = "wasm32", target_os = "unknown")))] use getrandom::getrandom; -#[no_mangle] -pub fn _start() { +proxy_wasm::main! {{ proxy_wasm::set_log_level(LogLevel::Trace); proxy_wasm::set_root_context(|_| -> Box { Box::new(HelloWorld) }); -} +}} struct HelloWorld; diff --git a/examples/http_auth_random.rs b/examples/http_auth_random.rs index 732b2f5f..2faf85dc 100644 --- a/examples/http_auth_random.rs +++ b/examples/http_auth_random.rs @@ -17,11 +17,10 @@ use proxy_wasm::traits::*; use proxy_wasm::types::*; use std::time::Duration; -#[no_mangle] -pub fn _start() { +proxy_wasm::main! {{ proxy_wasm::set_log_level(LogLevel::Trace); proxy_wasm::set_http_context(|_, _| -> Box { Box::new(HttpAuthRandom) }); -} +}} struct HttpAuthRandom; diff --git a/examples/http_body.rs b/examples/http_body.rs index 41eec096..bb2fef00 100644 --- a/examples/http_body.rs +++ b/examples/http_body.rs @@ -15,11 +15,10 @@ use proxy_wasm::traits::*; use proxy_wasm::types::*; -#[no_mangle] -pub fn _start() { +proxy_wasm::main! {{ proxy_wasm::set_log_level(LogLevel::Trace); proxy_wasm::set_root_context(|_| -> Box { Box::new(HttpBodyRoot) }); -} +}} struct HttpBodyRoot; diff --git a/examples/http_config.rs b/examples/http_config.rs index 790c259c..7493bf5f 100644 --- a/examples/http_config.rs +++ b/examples/http_config.rs @@ -15,15 +15,14 @@ use proxy_wasm::traits::*; use proxy_wasm::types::*; -#[no_mangle] -pub fn _start() { +proxy_wasm::main! {{ proxy_wasm::set_log_level(LogLevel::Trace); proxy_wasm::set_root_context(|_| -> Box { Box::new(HttpConfigHeaderRoot { header_content: String::new(), }) }); -} +}} struct HttpConfigHeader { header_content: String, diff --git a/examples/http_headers.rs b/examples/http_headers.rs index 0af2b528..3f3e2568 100644 --- a/examples/http_headers.rs +++ b/examples/http_headers.rs @@ -16,11 +16,10 @@ use log::trace; use proxy_wasm::traits::*; use proxy_wasm::types::*; -#[no_mangle] -pub fn _start() { +proxy_wasm::main! {{ proxy_wasm::set_log_level(LogLevel::Trace); proxy_wasm::set_root_context(|_| -> Box { Box::new(HttpHeadersRoot) }); -} +}} struct HttpHeadersRoot; diff --git a/src/lib.rs b/src/lib.rs index fa8c7ca5..a8f42651 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -20,6 +20,40 @@ mod allocator; mod dispatcher; mod logger; +// For crate-type="cdylib". +#[cfg(not(wasi_exec_model_reactor))] +#[macro_export] +macro_rules! main { + ($code:block) => { + #[cfg(target_os = "wasi")] + extern "C" { + fn __wasm_call_ctors(); + } + + #[no_mangle] + pub extern "C" fn _initialize() { + #[cfg(target_os = "wasi")] + unsafe { + __wasm_call_ctors(); + } + + $code; + } + }; +} + +// For crate-type="bin" with RUSTFLAGS="-Z wasi-exec-model=reactor". +#[cfg(wasi_exec_model_reactor)] +#[macro_export] +macro_rules! main { + ($code:block) => { + pub fn main() -> Result<(), Box> { + $code; + Ok(()) + } + }; +} + pub fn set_log_level(level: types::LogLevel) { logger::set_log_level(level); } From 104bcb6c7064f74e046e83c2866c9c7f248a3212 Mon Sep 17 00:00:00 2001 From: Piotr Sikora Date: Tue, 5 Apr 2022 01:25:01 -0700 Subject: [PATCH 2/4] review: add cargo:rerun-if-changed to the build script. Signed-off-by: Piotr Sikora --- build.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/build.rs b/build.rs index 2d668733..39a1dec1 100644 --- a/build.rs +++ b/build.rs @@ -13,11 +13,15 @@ // limitations under the License. fn main() { + println!("cargo:rerun-if-changed=build.rs"); + println!("cargo:rerun-if-env-changed=RUSTFLAGS"); + if let Some(target_os) = std::env::var_os("CARGO_CFG_TARGET_OS") { if target_os != "wasi" { return; } } + if let Some(rustflags) = std::env::var_os("CARGO_ENCODED_RUSTFLAGS") { for flag in rustflags.to_string_lossy().split('\x1f') { if flag.ends_with("wasi-exec-model=reactor") { From 2cfac75a0cfb48983fd8b52fb210c2b6eb895ef8 Mon Sep 17 00:00:00 2001 From: Piotr Sikora Date: Wed, 6 Apr 2022 23:30:44 -0700 Subject: [PATCH 3/4] review: apply Swaagie's suggestion. Signed-off-by: Piotr Sikora --- .github/workflows/rust.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 4ba91618..bd3d788c 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -208,7 +208,9 @@ jobs: rustup default nightly - name: Rewrite Cargo.toml examples - run: grep -v '^crate-type' Cargo.toml > Cargo.tmp && mv Cargo.tmp Cargo.toml + run: | + grep -v '^crate-type' Cargo.toml > Cargo.tmp + mv Cargo.tmp Cargo.toml - name: Build (wasm32-wasi) env: From d7b114e5d9298762525123e3aa6b7f41ade5a8b7 Mon Sep 17 00:00:00 2001 From: Piotr Sikora Date: Thu, 7 Apr 2022 01:34:45 -0700 Subject: [PATCH 4/4] review: update text in CHANGELOG.md. Signed-off-by: Piotr Sikora --- CHANGELOG.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 50ac6191..1bf76d89 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,10 +6,14 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ## [Unreleased] +### Fixed + +- Fixed performance degradation with `wasm32-wasi` target in Rust v1.56.0 + or newer by adding `proxy_wasm::main` macro that should be used instead + of custom `_start`, `_initialize` and/or `main` exports. + ### Changed -- Added `proxy_wasm::main` macro that should be used instead of custom `_start`, - `_initialize` and/or `main` exports. - Updated ABI to Proxy-Wasm ABI v0.2.1. ## [0.1.4] - 2021-07-01