diff --git a/packages/cli/src/lib/defaults/build-images/wasm/rust/Dockerfile.mustache b/packages/cli/src/lib/defaults/build-images/wasm/rust/Dockerfile.mustache index f1d6c9c99f..8cc17a2c28 100644 --- a/packages/cli/src/lib/defaults/build-images/wasm/rust/Dockerfile.mustache +++ b/packages/cli/src/lib/defaults/build-images/wasm/rust/Dockerfile.mustache @@ -32,6 +32,8 @@ WORKDIR /linked-packages COPY {{dir}} ./{{name}} {{/polywrap_linked_packages}} +WORKDIR / +RUN USER=root cargo new --lib project WORKDIR /project # Copy all manifest files @@ -39,13 +41,8 @@ WORKDIR /project COPY {{.}} . {{/polywrap_manifests}} -# Copy all source files -{{#include}} -COPY {{.}} {{.}} -{{/include}} -{{#polywrap_module}} -COPY {{dir}} {{dir}} -{{/polywrap_module}} +# Copy Cargo manifest files +COPY ./{{dir}}/Cargo.toml ./{{dir}}/Cargo.toml {{#polywrap_linked_packages.length}} # Link any local packages @@ -58,15 +55,10 @@ RUN PACKAGE_NAME={{name}}; \ {{/polywrap_module}} true {{/polywrap_linked_packages}} - {{/polywrap_linked_packages.length}} {{#polywrap_module}} -# Remove any Cargo.lock files -RUN rm -rf {{dir}}/Cargo.lock - -# Ensure the Wasm module is configured to use imported memory -ENV RUSTFLAGS="-C link-arg=-z -C link-arg=stack-size=65536 -C link-arg=--import-memory" +# Mock build for dependencies: # Ensure the module at {{dir}} has the crate-type = ["cdylib"] RUN toml set ./{{dir}}/Cargo.toml lib.crate-type ["cdylib"] > ./{{dir}}/Cargo-local.toml && \ @@ -83,14 +75,29 @@ RUN toml set ./{{dir}}/Cargo.toml package.name "module" > ./{{dir}}/Cargo-local. mv ./{{dir}}/Cargo-local.toml ./{{dir}}/Cargo.toml && \ true -# Make the build directory -RUN rm -rf ./build -RUN mkdir ./build +RUN cargo build --manifest-path ./{{dir}}/Cargo.toml --release + +# Copy all source files +{{#include}} +COPY {{.}} {{.}} +{{/include}} +RUN mv ./{{dir}}/Cargo.toml ./{{dir}}/Cargo-deps.toml +COPY {{dir}} {{dir}} +RUN mv ./{{dir}}/Cargo-deps.toml ./{{dir}}/Cargo.toml && rm ./target/release/deps/module* + +# Actual build: + +# Ensure the Wasm module is configured to use imported memory +ENV RUSTFLAGS="-C link-arg=-z -C link-arg=stack-size=65536 -C link-arg=--import-memory" # Build the module at {{dir}} RUN cargo build --manifest-path ./{{dir}}/Cargo.toml \ --target wasm32-unknown-unknown --release +# Make the build directory +RUN rm -rf ./build +RUN mkdir ./build + # Enable the "WASM_INTERFACE_TYPES" feature, which will remove the __wbindgen_throw import. # See: https://github.com/rustwasm/wasm-bindgen/blob/7f4663b70bd492278bf0e7bba4eeddb3d840c868/crates/cli-support/src/lib.rs#L397-L403 ENV WASM_INTERFACE_TYPES=1 diff --git a/packages/js/client/src/__tests__/e2e/wasm-rs.spec.ts b/packages/js/client/src/__tests__/e2e/wasm-rs.spec.ts index 3697caa667..b320528b19 100644 --- a/packages/js/client/src/__tests__/e2e/wasm-rs.spec.ts +++ b/packages/js/client/src/__tests__/e2e/wasm-rs.spec.ts @@ -1,6 +1,7 @@ import { PolywrapClientConfig, createPolywrapClient, + PolywrapClient, } from "../.."; import * as TestCases from "./test-cases"; import { makeMemoryStoragePlugin } from "./memory-storage"; @@ -12,6 +13,10 @@ import { providers } from "@polywrap/test-env-js"; import { GetPathToTestWrappers } from "@polywrap/test-cases"; +import fse from "fs-extra"; +import path from "path"; +import { execSync } from "child_process"; +const { performance } = require("perf_hooks"); jest.setTimeout(1200000); @@ -330,3 +335,95 @@ describe("wasm-rs test cases", () => { ); }) }); + +describe.skip("Wasm-rs benchmarking", () => { + const wrapperPath = `${GetPathToTestWrappers()}/wasm-rs/benchmarks` + const wrapperUri = `fs/${wrapperPath}/build` + + let cacheFiles = new Map(); + const mockFunc = ` + fn froo() -> &'static str { +"foo" +} + `; + + const modifySource = () => { + const libPath = path.join(wrapperPath, "src", "lib.rs"); + const libFile = fse.readFileSync(libPath, "utf-8"); + + cacheFiles.set(libPath, libFile); + + const modifiedFile = `${libFile}\n${mockFunc}`; + + fse.writeFileSync(libPath, modifiedFile); + }; + + const buildImage = async (name: "current" | "new"): Promise => { + const startTime = performance.now(); + + await buildWrapper( + wrapperPath, + name === "current"? "./polywrap-current.yaml": "./polywrap.yaml" + ); + + const endTime = performance.now(); + const msTime = endTime - startTime; + + //Make sure the wrapper works correctly + await TestCases.runBigNumberTypeTest( + new PolywrapClient(), wrapperUri + ); + + return msTime + }; + + beforeEach(() => { + fse.removeSync(`${wrapperPath}/build`); + fse.removeSync(`${wrapperPath}/.polywrap`); + }); + + const restoreSource = () => { + for (const [key, value] of cacheFiles) { + fse.writeFileSync(key, value); + } + }; + + it("Build image performance", async () => { + //Delete cached images and containers + execSync(`docker system prune -a -f`); + + //Build the wrapper with no previously cached images + const firstBuildTimeNew = await buildImage("new"); + console.log(`1st build - no cache (new): ${firstBuildTimeNew.toFixed(2)}ms`); + + //Build the wrapper again + const secondBuildTimeNew = await buildImage("new"); + console.log(`2nd build - with cache (new): ${secondBuildTimeNew.toFixed(2)}ms`); + + //Modify the source code and measure build time + modifySource(); + + const timeAfterSourceNew = await buildImage("new",); + console.log(`3rd build - modified source (new): ${timeAfterSourceNew.toFixed(2)}ms`); + + restoreSource(); + + // Repeat the process for current image and compare + execSync(`docker system prune -a -f`); + + const firstBuildTimeCurrent = await buildImage("current"); + console.log(`1st build - no cache (current): ${firstBuildTimeCurrent.toFixed(2)}ms`); + + const secondBuildTimeCurrent = await buildImage("current"); + console.log(`2nd build - with cache (current): ${secondBuildTimeCurrent.toFixed(2)}ms`); + + modifySource(); + + const timeAfterSourceCurrent = await buildImage("current"); + console.log(`3rd build - modified source (current): ${timeAfterSourceCurrent.toFixed(2)}ms`); + + restoreSource(); + + expect(timeAfterSourceNew).toBeLessThan(timeAfterSourceCurrent); + }) +}) diff --git a/packages/js/test-env/src/index.ts b/packages/js/test-env/src/index.ts index e29c4d60fa..023d0a556c 100644 --- a/packages/js/test-env/src/index.ts +++ b/packages/js/test-env/src/index.ts @@ -193,8 +193,13 @@ export const runCLI = async (options: { }; }; -export async function buildWrapper(wrapperAbsPath: string): Promise { - const manifestPath = `${wrapperAbsPath}/polywrap.yaml`; +export async function buildWrapper( + wrapperAbsPath: string, + manifestPathOverride?: string +): Promise { + const manifestPath = manifestPathOverride + ? path.join(wrapperAbsPath, manifestPathOverride) + : `${wrapperAbsPath}/polywrap.yaml`; const { exitCode: buildExitCode, stdout: buildStdout, diff --git a/packages/test-cases/cases/cli/wasm/build-benchmarks/001-rust/current/Dockerfile b/packages/test-cases/cases/cli/wasm/build-benchmarks/001-rust/current/Dockerfile new file mode 100644 index 0000000000..b8bee99161 --- /dev/null +++ b/packages/test-cases/cases/cli/wasm/build-benchmarks/001-rust/current/Dockerfile @@ -0,0 +1,80 @@ +FROM rust:1.60.0 as base + +# Install the wasm32 rust build target +RUN rustup target add wasm32-unknown-unknown + +WORKDIR /build-deps + +# Install curl +RUN apt-get update +RUN apt-get -y install curl clang llvm build-essential + +# Install wasm-opt +RUN curl -L https://github.com/WebAssembly/binaryen/releases/download/version_101/binaryen-version_101-x86_64-linux.tar.gz | tar -xz \ + && chmod +x binaryen-version_101/bin/wasm-opt \ + && cp binaryen-version_101/bin/wasm-opt /usr/local/bin/ \ + && rm -rf binary-version_101 + +# Install the toml-cli +RUN cargo install -f toml-cli + +# Install wasm-snip +RUN cargo install -f wasm-snip + +# Install wasm-bindgen +RUN cargo install -f wasm-bindgen-cli + +WORKDIR /project + +# Copy all manifest files +COPY polywrap.yaml . +COPY polywrap.build.yaml . + +# Copy all source files +COPY ./Cargo.toml ./Cargo.toml +COPY ./src ./src +COPY ./schema.graphql ./schema.graphql +COPY ./plugin.schema.graphql ./plugin.schema.graphql + +# Remove any Cargo.lock files +RUN rm -rf ./Cargo.lock + +# Ensure the Wasm module is configured to use imported memory +ENV RUSTFLAGS="-C link-arg=-z -C link-arg=stack-size=65536 -C link-arg=--import-memory" + +# Ensure the module at . has the crate-type = ["cdylib"] +RUN toml set ././Cargo.toml lib.crate-type ["cdylib"] > ././Cargo-local.toml && \ + rm -rf ././Cargo.toml && \ + mv ././Cargo-local.toml ././Cargo.toml && \ + true + +# Clean up artifacts left by the toml CLI program ("["cdylib"]" -> ["cdylib"]) +RUN sed -i 's/"\[cdylib\]"/\["cdylib"\]/g' ././Cargo.toml + +# Ensure the package name = "module" +RUN toml set ././Cargo.toml package.name "module" > ././Cargo-local.toml && \ + rm -rf ././Cargo.toml && \ + mv ././Cargo-local.toml ././Cargo.toml && \ + true + +# Make the build directory +RUN rm -rf ./build +RUN mkdir ./build + +# Build the module at . +RUN cargo build --manifest-path ././Cargo.toml \ + --target wasm32-unknown-unknown --release + +# Enable the "WASM_INTERFACE_TYPES" feature, which will remove the __wbindgen_throw import. +# See: https://github.com/rustwasm/wasm-bindgen/blob/7f4663b70bd492278bf0e7bba4eeddb3d840c868/crates/cli-support/src/lib.rs#L397-L403 +ENV WASM_INTERFACE_TYPES=1 + +# Run wasm-bindgen over the module, replacing all placeholder __wbindgen_... imports +RUN wasm-bindgen ././target/wasm32-unknown-unknown/release/module.wasm --out-dir ./build --out-name bg_module.wasm + +RUN wasm-snip ./build/bg_module.wasm -o ./build/snipped_module.wasm && \ + rm -rf ./build/bg_module.wasm + +# Use wasm-opt to perform the "asyncify" post-processing step over all modules +RUN wasm-opt --asyncify -Os ./build/snipped_module.wasm -o ./build/wrap.wasm && \ + rm -rf ./build/snipped_module.wasm diff --git a/packages/test-cases/cases/wrappers/wasm-rs/benchmarks/Cargo.toml b/packages/test-cases/cases/wrappers/wasm-rs/benchmarks/Cargo.toml new file mode 100644 index 0000000000..c2917828f4 --- /dev/null +++ b/packages/test-cases/cases/wrappers/wasm-rs/benchmarks/Cargo.toml @@ -0,0 +1,24 @@ +[package] +name = "module" +version = "0.1.0" +description = "Query module of bigint-type e2e test" +authors = [ + "Kobby Pentangeli ", + "Jordan Ellis " +] +repository = "https://github.com/polywrap/monorepo" +license = "MIT" +edition = "2021" + +[dependencies] +polywrap-wasm-rs = { path = "../../../../../../wasm/rs" } +serde = { version = "1.0", features = ["derive"] } +ethers = "0.14.0" + +[lib] +crate-type = ["cdylib"] + +[profile.release] +opt-level = 's' +lto = true +panic = 'abort' diff --git a/packages/test-cases/cases/wrappers/wasm-rs/benchmarks/Dockerfile b/packages/test-cases/cases/wrappers/wasm-rs/benchmarks/Dockerfile new file mode 100644 index 0000000000..c668f044f0 --- /dev/null +++ b/packages/test-cases/cases/wrappers/wasm-rs/benchmarks/Dockerfile @@ -0,0 +1,89 @@ +FROM rust:1.60.0 as base + +# Install the wasm32 rust build target +RUN rustup target add wasm32-unknown-unknown + +WORKDIR /build-deps + +# Install curl +RUN apt-get update +RUN apt-get -y install curl clang llvm build-essential + +# Install wasm-opt +RUN curl -L https://github.com/WebAssembly/binaryen/releases/download/version_101/binaryen-version_101-x86_64-linux.tar.gz | tar -xz \ + && chmod +x binaryen-version_101/bin/wasm-opt \ + && cp binaryen-version_101/bin/wasm-opt /usr/local/bin/ \ + && rm -rf binary-version_101 + +# Install the toml-cli +RUN cargo install -f toml-cli + +# Install wasm-snip +RUN cargo install -f wasm-snip + +# Install wasm-bindgen +RUN cargo install -f wasm-bindgen-cli + +WORKDIR /linked-packages + +COPY .polywrap/wasm/build/linked-packages/polywrap-wasm-rs ./polywrap-wasm-rs + +WORKDIR /project + +# Copy all manifest files +COPY polywrap.yaml . +COPY polywrap.build.yaml . + +# Copy all source files +COPY . . + +# Link any local packages +RUN PACKAGE_NAME=polywrap-wasm-rs; \ + toml set ././Cargo.toml dependencies.$PACKAGE_NAME.path /linked-packages/$PACKAGE_NAME > ././Cargo-local.toml && \ + rm -rf ././Cargo.toml && \ + mv ././Cargo-local.toml ././Cargo.toml && \ + true + + +# Remove any Cargo.lock files +RUN rm -rf ./Cargo.lock + +# Ensure the Wasm module is configured to use imported memory +ENV RUSTFLAGS="-C link-arg=-z -C link-arg=stack-size=65536 -C link-arg=--import-memory" + +# Ensure the module at . has the crate-type = ["cdylib"] +RUN toml set ././Cargo.toml lib.crate-type ["cdylib"] > ././Cargo-local.toml && \ + rm -rf ././Cargo.toml && \ + mv ././Cargo-local.toml ././Cargo.toml && \ + true + +# Clean up artifacts left by the toml CLI program ("["cdylib"]" -> ["cdylib"]) +RUN sed -i 's/"\[cdylib\]"/\["cdylib"\]/g' ././Cargo.toml + +# Ensure the package name = "module" +RUN toml set ././Cargo.toml package.name "module" > ././Cargo-local.toml && \ + rm -rf ././Cargo.toml && \ + mv ././Cargo-local.toml ././Cargo.toml && \ + true + +# Make the build directory +RUN rm -rf ./build +RUN mkdir ./build + +# Build the module at . +RUN cargo build --manifest-path ././Cargo.toml \ + --target wasm32-unknown-unknown --release + +# Enable the "WASM_INTERFACE_TYPES" feature, which will remove the __wbindgen_throw import. +# See: https://github.com/rustwasm/wasm-bindgen/blob/7f4663b70bd492278bf0e7bba4eeddb3d840c868/crates/cli-support/src/lib.rs#L397-L403 +ENV WASM_INTERFACE_TYPES=1 + +# Run wasm-bindgen over the module, replacing all placeholder __wbindgen_... imports +RUN wasm-bindgen ././target/wasm32-unknown-unknown/release/module.wasm --out-dir ./build --out-name bg_module.wasm + +RUN wasm-snip ./build/bg_module.wasm -o ./build/snipped_module.wasm && \ + rm -rf ./build/bg_module.wasm + +# Use wasm-opt to perform the "asyncify" post-processing step over all modules +RUN wasm-opt --asyncify -Os ./build/snipped_module.wasm -o ./build/wrap.wasm && \ + rm -rf ./build/snipped_module.wasm diff --git a/packages/test-cases/cases/wrappers/wasm-rs/benchmarks/polywrap-current.build.yaml b/packages/test-cases/cases/wrappers/wasm-rs/benchmarks/polywrap-current.build.yaml new file mode 100644 index 0000000000..34273c0f89 --- /dev/null +++ b/packages/test-cases/cases/wrappers/wasm-rs/benchmarks/polywrap-current.build.yaml @@ -0,0 +1,7 @@ +format: 0.1.0 +docker: + name: benchmark-type-wasm-rs + dockerfile: ./Dockerfile +linked_packages: + - name: polywrap-wasm-rs + path: ../../../../../wasm/rs diff --git a/packages/test-cases/cases/wrappers/wasm-rs/benchmarks/polywrap-current.yaml b/packages/test-cases/cases/wrappers/wasm-rs/benchmarks/polywrap-current.yaml new file mode 100644 index 0000000000..7aaef9a573 --- /dev/null +++ b/packages/test-cases/cases/wrappers/wasm-rs/benchmarks/polywrap-current.yaml @@ -0,0 +1,6 @@ +format: 0.1.0 +name: Benchmark +language: wasm/rust +build: ./polywrap-current.build.yaml +schema: ./schema.graphql +module: ./Cargo.toml diff --git a/packages/test-cases/cases/wrappers/wasm-rs/benchmarks/polywrap.build.yaml b/packages/test-cases/cases/wrappers/wasm-rs/benchmarks/polywrap.build.yaml new file mode 100644 index 0000000000..32d37799e7 --- /dev/null +++ b/packages/test-cases/cases/wrappers/wasm-rs/benchmarks/polywrap.build.yaml @@ -0,0 +1,6 @@ +format: 0.1.0 +docker: + name: benchmark-type-wasm-rs +linked_packages: + - name: polywrap-wasm-rs + path: ../../../../../wasm/rs diff --git a/packages/test-cases/cases/wrappers/wasm-rs/benchmarks/polywrap.yaml b/packages/test-cases/cases/wrappers/wasm-rs/benchmarks/polywrap.yaml new file mode 100644 index 0000000000..ff6d4389da --- /dev/null +++ b/packages/test-cases/cases/wrappers/wasm-rs/benchmarks/polywrap.yaml @@ -0,0 +1,6 @@ +format: 0.1.0 +name: Benchmark +language: wasm/rust +build: ./polywrap.build.yaml +schema: ./schema.graphql +module: ./Cargo.toml diff --git a/packages/test-cases/cases/wrappers/wasm-rs/benchmarks/schema.graphql b/packages/test-cases/cases/wrappers/wasm-rs/benchmarks/schema.graphql new file mode 100644 index 0000000000..ffe506dec2 --- /dev/null +++ b/packages/test-cases/cases/wrappers/wasm-rs/benchmarks/schema.graphql @@ -0,0 +1,12 @@ +type Module { + method( + arg1: BigNumber! + arg2: BigNumber + obj: BigNumberArg! + ): BigNumber! +} + +type BigNumberArg { + prop1: BigNumber! + prop2: BigNumber +} diff --git a/packages/test-cases/cases/wrappers/wasm-rs/benchmarks/src/lib.rs b/packages/test-cases/cases/wrappers/wasm-rs/benchmarks/src/lib.rs new file mode 100644 index 0000000000..5e5b5ae13c --- /dev/null +++ b/packages/test-cases/cases/wrappers/wasm-rs/benchmarks/src/lib.rs @@ -0,0 +1,18 @@ +use std::ops::Mul; + +use polywrap_wasm_rs::BigNumber; +pub mod wrap; +pub use wrap::*; + +pub fn method(args: ArgsMethod) -> BigNumber { + let mut result = args.arg1.mul(args.obj.prop1); + + if args.arg2.is_some() { + result = result.mul(args.arg2.unwrap()); + } + if args.obj.prop2.is_some() { + result = result.mul(args.obj.prop2.unwrap()); + } + + result +}