diff --git a/.github/workflows/format.yml b/.github/workflows/format.yml index 051459d7..8f61d358 100644 --- a/.github/workflows/format.yml +++ b/.github/workflows/format.yml @@ -43,7 +43,7 @@ jobs: addlicense: name: verify licenses - runs-on: ubuntu-24.04 + runs-on: ubuntu-24.04-16core steps: - uses: actions/checkout@v2 @@ -63,7 +63,7 @@ jobs: buildifier: name: check format with buildifier - runs-on: ubuntu-24.04 + runs-on: ubuntu-24.04-16core steps: - uses: actions/checkout@v2 @@ -101,7 +101,7 @@ jobs: clang_format: name: check format with clang-format - runs-on: ubuntu-24.04 + runs-on: ubuntu-24.04-16core steps: - uses: actions/checkout@v2 @@ -117,7 +117,7 @@ jobs: clang_tidy: name: check format with clang-tidy - runs-on: ubuntu-24.04 + runs-on: ubuntu-24.04-16core steps: - uses: actions/checkout@v2 diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 8c42a546..cc6ddbc5 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -43,7 +43,7 @@ jobs: test_data: name: build test data - runs-on: ubuntu-24.04 + runs-on: ubuntu-24.04-16core steps: - uses: actions/checkout@v2 @@ -128,19 +128,19 @@ jobs: include: - name: 'NullVM on Linux/x86_64' engine: 'null' - os: ubuntu-24.04 + os: ubuntu-24.04-16core arch: x86_64 action: test flags: --config=gcc - name: 'NullVM on Linux/x86_64 with ASan' engine: 'null' - os: ubuntu-24.04 + os: ubuntu-24.04-16core arch: x86_64 action: test flags: --config=clang-asan --define=crypto=system - name: 'NullVM on Linux/x86_64 with TSan' engine: 'null' - os: ubuntu-24.04 + os: ubuntu-24.04-16core arch: x86_64 action: test flags: --config=clang-tsan @@ -153,7 +153,7 @@ jobs: - name: 'V8 on Linux/x86_64' engine: 'v8' repo: 'v8' - os: ubuntu-24.04 + os: ubuntu-24.04-16core arch: x86_64 action: test flags: --config=hermetic-llvm --define=crypto=system @@ -161,7 +161,7 @@ jobs: - name: 'V8 on Linux/x86_64 with ASan' engine: 'v8' repo: 'v8' - os: ubuntu-24.04 + os: ubuntu-24.04-16core arch: x86_64 action: test flags: --config=hermetic-llvm --config=clang-asan @@ -169,7 +169,7 @@ jobs: - name: 'V8 on Linux/x86_64 with TSan' engine: 'v8' repo: 'v8' - os: ubuntu-24.04 + os: ubuntu-24.04-16core arch: x86_64 action: test flags: --config=hermetic-llvm --config=clang-tsan @@ -177,7 +177,7 @@ jobs: - name: 'V8 on Linux/x86_64 with GCC' engine: 'v8' repo: 'v8' - os: ubuntu-24.04 + os: ubuntu-24.04-16core arch: x86_64 action: test flags: --config=gcc @@ -202,7 +202,7 @@ jobs: - name: 'WAMR interp on Linux/x86_64' engine: 'wamr-interp' repo: 'com_github_bytecodealliance_wasm_micro_runtime' - os: ubuntu-24.04 + os: ubuntu-24.04-16core arch: x86_64 action: test flags: --config=clang @@ -215,7 +215,7 @@ jobs: - name: 'WAMR jit on Linux/x86_64' engine: 'wamr-jit' repo: 'com_github_bytecodealliance_wasm_micro_runtime' - os: ubuntu-24.04 + os: ubuntu-24.04-16core arch: x86_64 action: test flags: --config=clang @@ -231,7 +231,7 @@ jobs: - name: 'WasmEdge on Linux/x86_64' engine: 'wasmedge' repo: 'com_github_wasmedge_wasmedge' - os: ubuntu-24.04 + os: ubuntu-24.04-16core arch: x86_64 action: test flags: --config=clang @@ -244,14 +244,14 @@ jobs: - name: 'Wasmtime on Linux/x86_64' engine: 'wasmtime' repo: 'com_github_bytecodealliance_wasmtime' - os: ubuntu-24.04 + os: ubuntu-24.04-16core arch: x86_64 action: test flags: --config=clang -c opt - name: 'Wasmtime on Linux/x86_64 with ASan' engine: 'wasmtime' repo: 'com_github_bytecodealliance_wasmtime' - os: ubuntu-24.04 + os: ubuntu-24.04-16core arch: x86_64 action: test flags: --config=clang-asan --define=crypto=system @@ -265,7 +265,7 @@ jobs: - name: 'Wasmtime on Linux/s390x' engine: 'wasmtime' repo: 'com_github_bytecodealliance_wasmtime' - os: ubuntu-24.04 + os: ubuntu-24.04-16core arch: s390x action: test flags: --config=clang --test_timeout=1800 diff --git a/bazel/repositories.bzl b/bazel/repositories.bzl index 09939a70..8e6e3c88 100644 --- a/bazel/repositories.bzl +++ b/bazel/repositories.bzl @@ -34,10 +34,10 @@ def proxy_wasm_cpp_host_repositories(): http_archive, name = "bazel_skylib", urls = [ - "https://mirror.bazel.build/github.com/bazelbuild/bazel-skylib/releases/download/1.1.1/bazel-skylib-1.1.1.tar.gz", - "https://github.com/bazelbuild/bazel-skylib/releases/download/1.1.1/bazel-skylib-1.1.1.tar.gz", + "https://mirror.bazel.build/github.com/bazelbuild/bazel-skylib/releases/download/1.7.0/bazel-skylib-1.7.0.tar.gz", + "https://github.com/bazelbuild/bazel-skylib/releases/download/1.7.0/bazel-skylib-1.7.0.tar.gz", ], - sha256 = "c6966ec828da198c5d9adbaa94c05e3a1c7f21bd012a0b29ba8ddbccb2c93b0d", + sha256 = "d00f1389ee20b60018e92644e0948e16e350a7707219e7a390fb0a99b6ec9262", ) maybe( diff --git a/include/proxy-wasm/v8.h b/include/proxy-wasm/v8.h index 5531f52c..73c91b95 100644 --- a/include/proxy-wasm/v8.h +++ b/include/proxy-wasm/v8.h @@ -21,7 +21,6 @@ namespace proxy_wasm { -bool initV8Engine(); std::unique_ptr createV8Vm(); } // namespace proxy_wasm diff --git a/include/proxy-wasm/wamr.h b/include/proxy-wasm/wamr.h index 32a05e94..98ff72e3 100644 --- a/include/proxy-wasm/wamr.h +++ b/include/proxy-wasm/wamr.h @@ -21,7 +21,6 @@ namespace proxy_wasm { -bool initWamrEngine(); std::unique_ptr createWamrVm(); } // namespace proxy_wasm diff --git a/include/proxy-wasm/wasm_vm.h b/include/proxy-wasm/wasm_vm.h index c14624ac..9a2f0a6a 100644 --- a/include/proxy-wasm/wasm_vm.h +++ b/include/proxy-wasm/wasm_vm.h @@ -143,12 +143,25 @@ enum class AbiVersion { ProxyWasm_0_1_0, ProxyWasm_0_2_0, ProxyWasm_0_2_1, Unkno class NullPlugin; +enum class FailState : int { + Ok = 0, + UnableToCreateVm = 1, + UnableToCloneVm = 2, + MissingFunction = 3, + UnableToInitializeCode = 4, + StartFailed = 5, + ConfigureFailed = 6, + RuntimeError = 7, +}; + // Integrator specific WasmVm operations. struct WasmVmIntegration { virtual ~WasmVmIntegration() {} virtual WasmVmIntegration *clone() = 0; virtual proxy_wasm::LogLevel getLogLevel() = 0; virtual void error(std::string_view message) = 0; + // Allow integrations to handle specific FailStates differently. + virtual void error(FailState fail_state, std::string_view message) { error(message); } virtual void trace(std::string_view message) = 0; // Get a NullVm implementation of a function. // @param function_name is the name of the function with the implementation specific prefix. @@ -165,17 +178,6 @@ struct WasmVmIntegration { void *ptr_to_function_return) = 0; }; -enum class FailState : int { - Ok = 0, - UnableToCreateVm = 1, - UnableToCloneVm = 2, - MissingFunction = 3, - UnableToInitializeCode = 4, - StartFailed = 5, - ConfigureFailed = 6, - RuntimeError = 7, -}; - // Wasm VM instance. Provides the low level WASM interface. class WasmVm { public: @@ -308,14 +310,11 @@ class WasmVm { */ virtual bool usesWasmByteOrder() = 0; - /** - * Warm the VM such as engine and runtime. - */ - virtual void warm() = 0; + virtual void warm() {} bool isFailed() { return failed_ != FailState::Ok; } void fail(FailState fail_state, std::string_view message) { - integration()->error(message); + integration()->error(fail_state, message); failed_ = fail_state; for (auto &callback : fail_callbacks_) { callback(fail_state); diff --git a/include/proxy-wasm/wasmtime.h b/include/proxy-wasm/wasmtime.h index 11c4ae7a..e3fe4b48 100644 --- a/include/proxy-wasm/wasmtime.h +++ b/include/proxy-wasm/wasmtime.h @@ -18,7 +18,6 @@ namespace proxy_wasm { -bool initWasmtimeEngine(); std::unique_ptr createWasmtimeVm(); } // namespace proxy_wasm diff --git a/src/v8/v8.cc b/src/v8/v8.cc index 9e184f29..f5a73b13 100644 --- a/src/v8/v8.cc +++ b/src/v8/v8.cc @@ -28,9 +28,10 @@ #include "include/proxy-wasm/limits.h" +#include "absl/strings/str_format.h" +#include "include/v8-initialization.h" #include "include/v8-version.h" #include "include/v8.h" -#include "src/flags/flags.h" #include "src/wasm/c-api.h" #include "wasm-api/wasm.hh" @@ -42,10 +43,13 @@ wasm::Engine *engine() { static wasm::own engine; std::call_once(init, []() { - ::v8::internal::v8_flags.liftoff = false; - ::v8::internal::v8_flags.wasm_max_mem_pages = - PROXY_WASM_HOST_MAX_WASM_MEMORY_SIZE_BYTES / PROXY_WASM_HOST_WASM_MEMORY_PAGE_SIZE_BYTES; + // Disable the Liftoff compiler to force optimized JIT up-front. + std::string args = absl::StrFormat("--wasm_max_mem_pages=%u --no-liftoff", + PROXY_WASM_HOST_MAX_WASM_MEMORY_SIZE_BYTES / + PROXY_WASM_HOST_WASM_MEMORY_PAGE_SIZE_BYTES); + ::v8::V8::SetFlagsFromString(args.c_str(), args.size()); ::v8::V8::EnableWebAssemblyTrapHandler(true); + engine = wasm::Engine::make(); }); @@ -755,8 +759,6 @@ std::string V8::getFailMessage(std::string_view function_name, wasm::own createV8Vm() { return std::make_unique(); } } // namespace proxy_wasm diff --git a/src/wamr/wamr.cc b/src/wamr/wamr.cc index 88dc9f00..8eef7359 100644 --- a/src/wamr/wamr.cc +++ b/src/wamr/wamr.cc @@ -713,8 +713,6 @@ void Wamr::warm() { initStore(); } } // namespace wamr -bool initWamrEngine() { return wamr::engine() != nullptr; } - std::unique_ptr createWamrVm() { return std::make_unique(); } } // namespace proxy_wasm diff --git a/src/wasm.cc b/src/wasm.cc index e8a7ce43..a1b4c183 100644 --- a/src/wasm.cc +++ b/src/wasm.cc @@ -378,7 +378,9 @@ ContextBase *WasmBase::getRootContext(const std::shared_ptr &plugin, void WasmBase::startVm(ContextBase *root_context) { // wasi_snapshot_preview1.clock_time_get wasm_vm_->setRestrictedCallback( - true, {// logging (Proxy-Wasm) + true, {// emscripten + "env.emscripten_notify_memory_growth", + // logging (Proxy-Wasm) "env.proxy_log", // logging (stdout/stderr) "wasi_unstable.fd_write", "wasi_snapshot_preview1.fd_write", diff --git a/src/wasmedge/wasmedge.cc b/src/wasmedge/wasmedge.cc index 263ed188..30fe78f5 100644 --- a/src/wasmedge/wasmedge.cc +++ b/src/wasmedge/wasmedge.cc @@ -225,9 +225,6 @@ using HostModuleDataPtr = std::unique_ptr; class WasmEdge : public WasmVm { public: WasmEdge() { - loader_ = WasmEdge_LoaderCreate(nullptr); - validator_ = WasmEdge_ValidatorCreate(nullptr); - executor_ = WasmEdge_ExecutorCreate(nullptr, nullptr); store_ = nullptr; ast_module_ = nullptr; module_ = nullptr; @@ -305,6 +302,7 @@ class WasmEdge : public WasmVm { bool WasmEdge::load(std::string_view bytecode, std::string_view /*precompiled*/, const std::unordered_map & /*function_names*/) { + initStore(); WasmEdge_ASTModuleContext *mod = nullptr; WasmEdge_Result res = WasmEdge_LoaderParseFromBuffer( loader_.get(), &mod, reinterpret_cast(bytecode.data()), bytecode.size()); @@ -324,6 +322,9 @@ void WasmEdge::initStore() { if (store_ != nullptr) { return; } + loader_ = WasmEdge_LoaderCreate(nullptr); + validator_ = WasmEdge_ValidatorCreate(nullptr); + executor_ = WasmEdge_ExecutorCreate(nullptr, nullptr); store_ = WasmEdge_StoreCreate(); } diff --git a/src/wasmtime/wasmtime.cc b/src/wasmtime/wasmtime.cc index ac036162..a72a0361 100644 --- a/src/wasmtime/wasmtime.cc +++ b/src/wasmtime/wasmtime.cc @@ -710,8 +710,6 @@ void Wasmtime::warm() { initStore(); } } // namespace wasmtime -bool initWasmtimeEngine() { return wasmtime::engine() != nullptr; } - std::unique_ptr createWasmtimeVm() { return std::make_unique(); } } // namespace proxy_wasm diff --git a/test/wasm_vm_test.cc b/test/wasm_vm_test.cc index bb2bab19..346fe2a0 100644 --- a/test/wasm_vm_test.cc +++ b/test/wasm_vm_test.cc @@ -31,37 +31,17 @@ INSTANTIATE_TEST_SUITE_P(WasmEngines, TestVm, testing::ValuesIn(getWasmEngines() }); TEST_P(TestVm, Init) { - std::chrono::time_point time2; - auto time1 = std::chrono::steady_clock::now(); - if (engine_ == "v8") { -#if defined(PROXY_WASM_HOST_ENGINE_V8) - EXPECT_TRUE(proxy_wasm::initV8Engine()); - time2 = std::chrono::steady_clock::now(); - EXPECT_TRUE(proxy_wasm::initV8Engine()); -#endif - } else if (engine_ == "wamr") { -#if defined(PROXY_WASM_HOST_ENGINE_WAMR) - EXPECT_TRUE(proxy_wasm::initWamrEngine()); - time2 = std::chrono::steady_clock::now(); - EXPECT_TRUE(proxy_wasm::initWamrEngine()); -#endif - } else if (engine_ == "wasmtime") { -#if defined(PROXY_WASM_HOST_ENGINE_WASMTIME) - EXPECT_TRUE(proxy_wasm::initWasmtimeEngine()); - time2 = std::chrono::steady_clock::now(); - EXPECT_TRUE(proxy_wasm::initWasmtimeEngine()); -#endif - } else { - return; - } + vm_->warm(); + auto time2 = std::chrono::steady_clock::now(); + vm_->warm(); auto time3 = std::chrono::steady_clock::now(); auto cold = std::chrono::duration_cast(time2 - time1).count(); auto warm = std::chrono::duration_cast(time3 - time2).count(); - std::cout << "\"cold\" engine time: " << cold << "ns" << std::endl; - std::cout << "\"warm\" engine time: " << warm << "ns" << std::endl; + std::cout << "[" << engine_ << "] \"cold\" engine time: " << cold << "ns" << std::endl; + std::cout << "[" << engine_ << "] \"warm\" engine time: " << warm << "ns" << std::endl; // Default warm time in nanoseconds. int warm_time_ns_limit = 10000; @@ -75,6 +55,11 @@ TEST_P(TestVm, Init) { EXPECT_LE(warm, warm_time_ns_limit); // Verify that getting a "warm" engine takes at least 50x less time than getting a "cold" one. + // We skip NullVM because warm() is a noop. + if (engine_ == "null") { + std::cout << "Skipping warm() performance assertions for NullVM." << std::endl; + return; + } EXPECT_LE(warm * 50, cold); }