From f6d67c1cdad8c71f13b4072cc71c70c3652e058f Mon Sep 17 00:00:00 2001 From: "liang.he" Date: Mon, 5 Dec 2022 12:25:26 +0800 Subject: [PATCH] Enable wasm cache loading in wasm-c-api (#1759) Use sha256 to hash binary file content. If the incoming wasm binary is cached before, wasm_module_new() simply returns the existed one. Use -DWAMR_BUILD_WASM_CACHE=0/1 to control the feature. OpenSSL 1.1.1 is required if the feature is enabled. --- CMakeLists.txt | 6 +++ build-scripts/config_common.cmake | 4 ++ build-scripts/runtime_lib.cmake | 8 +++ core/config.h | 4 ++ core/iwasm/common/wasm_c_api.c | 83 ++++++++++++++++++++++++++++++- samples/wasm-c-api/CMakeLists.txt | 4 ++ 6 files changed, 107 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9ca63d7d4..f683868f2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -130,6 +130,9 @@ include (${SHARED_DIR}/utils/uncommon/shared_uncommon.cmake) # STATIC LIBRARY add_library(iwasm_static STATIC ${WAMR_RUNTIME_LIB_SOURCE}) +if (WAMR_BUILD_WASM_CACHE EQUAL 1) + target_link_libraries(iwasm_static OpenSSL::SSL) +endif () set_target_properties (iwasm_static PROPERTIES OUTPUT_NAME vmlib) install (TARGETS iwasm_static ARCHIVE DESTINATION lib) @@ -138,6 +141,9 @@ install (TARGETS iwasm_static ARCHIVE DESTINATION lib) add_library (iwasm_shared SHARED ${WAMR_RUNTIME_LIB_SOURCE}) set_target_properties (iwasm_shared PROPERTIES OUTPUT_NAME iwasm) target_link_libraries (iwasm_shared ${LLVM_AVAILABLE_LIBS} ${UV_A_LIBS} -lm -ldl -lpthread) +if (WAMR_BUILD_WASM_CACHE EQUAL 1) + target_link_libraries(iwasm_shared OpenSSL::SSL) +endif () if (MINGW) target_link_libraries (iwasm_shared -lWs2_32) diff --git a/build-scripts/config_common.cmake b/build-scripts/config_common.cmake index f10b5b4eb..7678d6818 100644 --- a/build-scripts/config_common.cmake +++ b/build-scripts/config_common.cmake @@ -314,3 +314,7 @@ endif () if (WAMR_BUILD_ALLOC_WITH_USER_DATA EQUAL 1) add_definitions(-DWASM_MEM_ALLOC_WITH_USER_DATA=1) endif() +if (WAMR_BUILD_WASM_CACHE EQUAL 1) + add_definitions (-DWASM_ENABLE_WASM_CACHE=1) + message (" Wasm files cache enabled") +endif () diff --git a/build-scripts/runtime_lib.cmake b/build-scripts/runtime_lib.cmake index c51958951..439a7c638 100644 --- a/build-scripts/runtime_lib.cmake +++ b/build-scripts/runtime_lib.cmake @@ -27,6 +27,14 @@ if (DEFINED EXTRA_SDK_INCLUDE_PATH) ) endif () +# Need exactly OpenSSL 1.1.1 +if (WAMR_BUILD_WASM_CACHE EQUAL 1) + # Set OPENSSL_ROOT_DIR to the root directory of an OpenSSL installation. + # Like: cmake -DOPENSSL_ROOT_DIR=/usr/local/opt/openssl + # Especially on MacOS + find_package(OpenSSL 1.1.1 EXACT REQUIRED) +endif () + # Set default options # Set WAMR_BUILD_TARGET, currently values supported: diff --git a/core/config.h b/core/config.h index 288160d02..5d6438384 100644 --- a/core/config.h +++ b/core/config.h @@ -430,4 +430,8 @@ #define WASM_MEM_ALLOC_WITH_USER_DATA 0 #endif +#ifndef WASM_ENABLE_WASM_CACHE +#define WASM_ENABLE_WASM_CACHE 0 +#endif + #endif /* end of _CONFIG_H_ */ diff --git a/core/iwasm/common/wasm_c_api.c b/core/iwasm/common/wasm_c_api.c index 1928cf14b..f6212d5de 100644 --- a/core/iwasm/common/wasm_c_api.c +++ b/core/iwasm/common/wasm_c_api.c @@ -2,6 +2,7 @@ * Copyright (C) 2019 Intel Corporation. All rights reserved. * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception */ + #include "wasm_c_api_internal.h" #include "bh_assert.h" @@ -18,6 +19,10 @@ #endif /*WASM_ENABLE_JIT != 0 && WASM_ENABLE_LAZY_JIT == 0*/ #endif /*WASM_ENABLE_AOT != 0*/ +#if WASM_ENABLE_WASM_CACHE != 0 +#include +#endif + /* * Thread Model: * - Only one wasm_engine_t in one process @@ -35,6 +40,9 @@ typedef struct wasm_module_ex_t { wasm_byte_vec_t *binary; korp_mutex lock; uint32 ref_count; +#if WASM_ENABLE_WASM_CACHE != 0 + char hash[SHA256_DIGEST_LENGTH]; +#endif } wasm_module_ex_t; #ifndef os_thread_local_attribute @@ -2087,16 +2095,68 @@ module_to_module_ext(wasm_module_t *module) #define MODULE_AOT(module_comm) ((AOTModule *)(*module_comm)) #endif +#if WASM_ENABLE_WASM_CACHE != 0 +static wasm_module_ex_t * +check_loaded_module(Vector *modules, char *binary_hash) +{ + unsigned i; + wasm_module_ex_t *module = NULL; + + for (i = 0; i < modules->num_elems; i++) { + bh_vector_get(modules, i, &module); + if (!module) { + LOG_ERROR("Unexpected failure at %d\n", __LINE__); + return NULL; + } + + if (!module->ref_count) + /* deleted */ + continue; + + if (memcmp(module->hash, binary_hash, SHA256_DIGEST_LENGTH) == 0) + return module; + } + return NULL; +} + +static wasm_module_ex_t * +try_reuse_loaded_module(wasm_store_t *store, char *binary_hash) +{ + wasm_module_ex_t *cached = NULL; + wasm_module_ex_t *ret = NULL; + + cached = check_loaded_module(&singleton_engine->modules, binary_hash); + if (!cached) + goto quit; + + os_mutex_lock(&cached->lock); + if (!cached->ref_count) + goto unlock; + + if (!bh_vector_append((Vector *)store->modules, &cached)) + goto unlock; + + cached->ref_count += 1; + ret = cached; + +unlock: + os_mutex_unlock(&cached->lock); +quit: + return ret; +} +#endif /* WASM_ENABLE_WASM_CACHE != 0 */ + wasm_module_t * wasm_module_new(wasm_store_t *store, const wasm_byte_vec_t *binary) { char error_buf[128] = { 0 }; wasm_module_ex_t *module_ex = NULL; +#if WASM_ENABLE_WASM_CACHE != 0 + char binary_hash[SHA256_DIGEST_LENGTH] = { 0 }; +#endif bh_assert(singleton_engine); - WASM_C_DUMP_PROC_MEM(); - if (!store || !binary || binary->size == 0 || binary->size > UINT32_MAX) goto quit; @@ -2121,6 +2181,16 @@ wasm_module_new(wasm_store_t *store, const wasm_byte_vec_t *binary) } } +#if WASM_ENABLE_WASM_CACHE != 0 + /* if cached */ + SHA256((void *)binary->data, binary->num_elems, binary_hash); + module_ex = try_reuse_loaded_module(store, binary_hash); + if (module_ex) + return module_ext_to_module(module_ex); +#endif + + WASM_C_DUMP_PROC_MEM(); + module_ex = malloc_internal(sizeof(wasm_module_ex_t)); if (!module_ex) goto quit; @@ -2151,6 +2221,11 @@ wasm_module_new(wasm_store_t *store, const wasm_byte_vec_t *binary) if (!bh_vector_append(&singleton_engine->modules, &module_ex)) goto destroy_lock; +#if WASM_ENABLE_WASM_CACHE != 0 + bh_memcpy_s(module_ex->hash, sizeof(module_ex->hash), binary_hash, + sizeof(binary_hash)); +#endif + module_ex->ref_count = 1; WASM_C_DUMP_PROC_MEM(); @@ -2226,6 +2301,10 @@ wasm_module_delete_internal(wasm_module_t *module) module_ex->module_comm_rt = NULL; } +#if WASM_ENABLE_WASM_CACHE != 0 + memset(module_ex->hash, 0, sizeof(module_ex->hash)); +#endif + os_mutex_unlock(&module_ex->lock); } diff --git a/samples/wasm-c-api/CMakeLists.txt b/samples/wasm-c-api/CMakeLists.txt index 3fce87c01..02b97d4cf 100644 --- a/samples/wasm-c-api/CMakeLists.txt +++ b/samples/wasm-c-api/CMakeLists.txt @@ -92,6 +92,10 @@ if (MSVC) target_compile_definitions(vmlib PRIVATE WASM_API_EXTERN=) endif() target_link_libraries (vmlib ${LLVM_AVAILABLE_LIBS} ${UV_A_LIBS} -lm -ldl -lpthread) + +if (WAMR_BUILD_WASM_CACHE EQUAL 1) + target_link_libraries(vmlib OpenSSL::SSL) +endif () ################################################ ################ application related ################