Skip to content
Snippets Groups Projects
Commit f98f2311 authored by Mohammad Mahhouk's avatar Mohammad Mahhouk
Browse files

added new benchmarking modules for the shared memory and exporting malloc from a module

parent b860cdab
No related branches found
No related tags found
No related merge requests found
......@@ -8,7 +8,7 @@ set (WASI_SDK_DIR ${CMAKE_CURRENT_SOURCE_DIR}/wasi-sdk)
set (WASI_CLANG ${WASI_SDK_DIR}/bin/clang)
set (WASI_SYSROOT ${WASI_SDK_DIR}/share/wasi-sysroot)
set (WAMR_EMBEDDING_API_INCLUDE_PATH ${WAMR_ROOT_DIR}/core/iwasm/include)
set (VM_LIB ${WAMR_ROOT_DIR}/product-mini/platforms/linux/build/libvmlib.a)
#set (VM_LIB ${WAMR_ROOT_DIR}/product-mini/platforms/linux/build/libvmlib.a)
set(CMAKE_CXX_COMPILER "clang++")
......@@ -76,6 +76,9 @@ file(GLOB WASM_FILES
"${CMAKE_BINARY_DIR}/multadd.wasm"
"${CMAKE_BINARY_DIR}/test.wasm"
"${CMAKE_BINARY_DIR}/key_value.wasm"
"${CMAKE_BINARY_DIR}/key_value_bench.wasm"
"${CMAKE_BINARY_DIR}/kv_shared_mem.wasm"
)
set_property(DIRECTORY PROPERTY ADDITIONAL_MAKE_CLEAN_FILES
......@@ -100,3 +103,15 @@ set(EXPORT_KEY_VALUE_SOURCE_FILES export_key_value/export_key_value.cpp)
add_executable(export_key_value ${EXPORT_KEY_VALUE_SOURCE_FILES})
target_include_directories(export_key_value PUBLIC ${WAMR_EMBEDDING_API_INCLUDE_PATH} ${CMAKE_CURRENT_LIST_DIR})
target_link_libraries(export_key_value PRIVATE vmlib pthread m)
if(BENCH_ITERATIONS)
target_compile_definitions(export_key_value PUBLIC -DBENCH_ITERATIONS=${BENCH_ITERATIONS})
endif()
set(EXPORT_KEY_VALUE_SHARED_MEM_SOURCE_FILES export_key_value_shared_mem/export_key_value_shared_mem.cpp)
add_executable(export_key_value_shared_mem ${EXPORT_KEY_VALUE_SHARED_MEM_SOURCE_FILES})
target_include_directories(export_key_value_shared_mem PUBLIC ${WAMR_EMBEDDING_API_INCLUDE_PATH} ${CMAKE_CURRENT_LIST_DIR})
target_link_libraries(export_key_value_shared_mem PRIVATE vmlib pthread m)
if(BENCH_ITERATIONS)
target_compile_definitions(export_key_value_shared_mem PUBLIC -DBENCH_ITERATIONS=${BENCH_ITERATIONS})
endif()
......@@ -4,9 +4,18 @@
#include <stdint.h>
#include <string.h>
#include "wasm_export.h"
#include <vector>
#include <map>
#include <iostream>
std::vector<char *> int_string_map = {};
#include <chrono>
#include <utility>
typedef std::chrono::high_resolution_clock::time_point TimeVar;
#define duration(a) std::chrono::duration_cast<std::chrono::nanoseconds>(a).count()
#define timeNow() std::chrono::high_resolution_clock::now()
std::map<int, char *> int_string_map = {{}};
......@@ -42,12 +51,7 @@ int get_key_value(wasm_exec_env_t exec_env, int index)
void set_key_value(wasm_exec_env_t exec_env, int index, char *value)
{
if (index > int_string_map.size())
{
printf("error index out of bound!\n");
exit(EXIT_FAILURE);
}
int_string_map.insert(int_string_map.begin()+index, value);
int_string_map[index] = value;
}
......@@ -98,6 +102,7 @@ char *read_wasm_binary_to_buffer(const char *path, uint32_t *size)
int main(int argc, char *argv[])
{
int_string_map[0]="test";
static NativeSymbol native_symbols[] =
{
{
......@@ -180,10 +185,18 @@ int main(int argc, char *argv[])
return -1;
}
uint32_t args[1] = {0};
#ifdef BENCH_ITERATIONS
TimeVar t1=timeNow();
#endif
if (wasm_runtime_call_wasm(exec_env, func, 0, args) ) {
/* the return value is stored in argv[0] */
//printf("the main function returned %ld \n", args[0]);
#ifdef BENCH_ITERATIONS
auto time_elapsed= duration(timeNow()-t1);
std::cout<< "total execution time is " << time_elapsed << "ns and " << time_elapsed/BENCH_ITERATIONS << "ns per function call on average" << std::endl;
#endif
}
else {
/* exception is thrown if call fails */
......
#include <cstdlib>
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include "wasm_export.h"
#include <map>
#include <iostream>
#include <chrono>
#include <utility>
typedef std::chrono::high_resolution_clock::time_point TimeVar;
#define duration(a) std::chrono::duration_cast<std::chrono::nanoseconds>(a).count()
#define timeNow() std::chrono::high_resolution_clock::now()
std::map<int, char *> int_string_map = {{}};
#ifndef SHARED_MEM_SIZE
#define SHARED_MEM_SIZE 1024
#endif
char *shared_mem=NULL;
int get_key_value(wasm_exec_env_t exec_env, int index)
{
if(index >= int_string_map.size())
{
printf("Error(get_key_value): index out of bound \n");
exit(EXIT_FAILURE);
}
strcpy(shared_mem, int_string_map[index]);
return strlen(int_string_map[index]);
}
void set_key_value(wasm_exec_env_t exec_env, int index, char *value)
{
int_string_map[index] = value;
}
char *read_wasm_binary_to_buffer(const char *path, uint32_t *size)
{
FILE *fd = fopen(path, "rb");
if(!fd)
{
fprintf(stderr,"failed to open the %s file\n", path);
perror("fopen failed!\n");
return NULL;
}
if (fseek(fd, 0, SEEK_END) != 0)
{
perror("fseek failed\n");
return NULL;
}
long fsize = ftell(fd);
if(fseek(fd, 0, SEEK_SET) != 0) // rewind(fd); can be used here too
{
perror("fseek failed\n");
return NULL;
}
char *buffer = (char *) malloc(fsize + 1);
if (!buffer)
{
perror("malloc for file buffer failed!\n");
return NULL;
}
size_t read_bytes = fread(buffer, 1, fsize, fd);
if(read_bytes != (size_t)fsize)
{
free(buffer);
fprintf(stderr, "file read didnt read the whole file size and returned only %zu instead of %zu \n", read_bytes, fsize);
exit(EXIT_FAILURE);
}
fclose(fd);
*size = fsize; //+ 1;
//buffer[fsize] = 0;
return buffer;
}
int main(int argc, char *argv[])
{
int_string_map[0]="test";
static NativeSymbol native_symbols[] =
{
{
"set_key_value", // the name of WASM function name
(void *) set_key_value, // the native function pointer
"(i$)", // the function prototype signature
NULL, // no attachments
},
{
"get_key_value", // the name of WASM function name
(void *) get_key_value, // the native function pointer
"(i)i", // the function prototype signature
NULL, // no attachments
}
};
char *buffer, error_buf[128];
wasm_module_t module;
wasm_module_inst_t module_inst;
wasm_function_inst_t func;
wasm_exec_env_t exec_env;
uint32_t size, stack_size = 8092, heap_size = 8092;
/* initialize the wasm runtime by default configurations */
if(!wasm_runtime_init())
{
fprintf(stderr,"wasm runtime initialisation failed\n");
exit(EXIT_FAILURE);
}
/* read WASM file into a memory buffer */
buffer = read_wasm_binary_to_buffer(argv[1], &size);
if(buffer == NULL)
{
fprintf(stderr, "the returned buffer for reading the wasm module is null\n");
exit(EXIT_FAILURE);
}
/* add line below if we want to export native functions to WASM app */
int n_native_symbols = sizeof(native_symbols) / sizeof(NativeSymbol);
if (!wasm_runtime_register_natives("env", native_symbols, n_native_symbols))
{
free(buffer);
exit(EXIT_FAILURE);
}
/* parse the WASM file from buffer and create a WASM module */
module = wasm_runtime_load((uint8_t *)buffer, size, error_buf, sizeof(error_buf));
if(module == NULL)
{
fprintf(stderr, "failed to load the module %s from the buffer with the error %s\n", argv[1], error_buf);
exit(EXIT_FAILURE);
}
/* create an instance of the WASM module (WASM linear memory is ready) */
module_inst = wasm_runtime_instantiate(module, stack_size, heap_size,
error_buf, sizeof(error_buf));
if(module_inst == NULL)
{
fprintf(stderr, "module instantiation failed!\n");
exit(EXIT_FAILURE);
}
wasm_function_inst_t init_shared_mem_func = wasm_runtime_lookup_function(module_inst, "init_shared_mem", "(i)i");
if (init_shared_mem_func == NULL) {
printf("init_shared_mem_func function not found\n");
return -1;
}
/* lookup a WASM function by its name
The function signature can NULL here */
func = wasm_runtime_lookup_function(module_inst, "main", "()i");
if (func == NULL) {
printf("main function not found\n");
return -1;
}
/* creat an execution environment to execute the WASM functions */
exec_env = wasm_runtime_create_exec_env(module_inst, stack_size);
if (exec_env == NULL) {
printf("execution environmnet creation failed\n");
return -1;
}
uint32_t shared_mem_args[2] = {0};
shared_mem_args[0] = SHARED_MEM_SIZE;
if (wasm_runtime_call_wasm(exec_env, init_shared_mem_func, 1, shared_mem_args) ) {
printf("shared memory is initialised with the size %d\n", SHARED_MEM_SIZE);
shared_mem = (char *) wasm_runtime_addr_app_to_native(module_inst,shared_mem_args[0]);
}
else {
/* exception is thrown if call fails */
printf("Error: calling init shared mem function %s\n", wasm_runtime_get_exception(module_inst));
exit(EXIT_FAILURE);
}
uint32_t args[1] = {0};
#ifdef BENCH_ITERATIONS
TimeVar t1=timeNow();
#endif
if (wasm_runtime_call_wasm(exec_env, func, 0, args) ) {
/* the return value is stored in argv[0] */
//printf("the main function returned %ld \n", args[0]);
#ifdef BENCH_ITERATIONS
auto time_elapsed= duration(timeNow()-t1);
std::cout<< "total execution time is " << time_elapsed << "ns and " << time_elapsed/BENCH_ITERATIONS << "ns per function call on average" << std::endl;
#endif
}
else {
/* exception is thrown if call fails */
printf("%s\n", wasm_runtime_get_exception(module_inst));
}
wasm_runtime_destroy();
return 0;
}
\ No newline at end of file
BENCH_ITERATIONS?=1000
C := ../wasi-sdk/bin/clang
#CFLAGS := --sysroot=../wasi-sdk-12.0/share/wasi-sysroot -Wl,--no-entry,--allow-undefined,--export-all -O3
CFLAGS := --sysroot=../wasi-sdk/share/wasi-sysroot -Wl,--no-entry -O3
CFLAGS := --sysroot=../wasi-sdk/share/wasi-sysroot -Wl,--no-entry -O3 -DBENCH_ITERATIONS=$(BENCH_ITERATIONS)
.PHONY: test add multadd key_value all
.PHONY: test add multadd key_value key_value_bench kv_shared_mem all
add: add.wasm
multadd: multadd.wasm
test: test.wasm
key_value: key_value.wasm
key_value_bench: key_value_bench.wasm
kv_shared_mem: kv_shared_mem.wasm
all: test add multadd key_value
all: test add multadd key_value key_value_bench kv_shared_mem
clean:
rm -f *.wasm
%.wasm: %.c
$(C) $(CFLAGS) -o $@ $<
$(C) $(CFLAGS) -o $@ $<
@echo "The benchmark iterations are set to $(BENCH_ITERATIONS)!"
\ No newline at end of file
#include <stdio.h>
#include <stdlib.h>
#define import(name) __attribute__((import_name(name)))
#define export(name) __attribute__((export_name(name))) __attribute__((visibility("default")))
import("get_key_value")
extern char* get_key_value(int index);
import("set_key_value")
extern void set_key_value(int index, char *value);
export("module_malloc")
char *module_malloc(int size){
if(size <= 0) return NULL;
char *result = (char*) malloc(size);
return result==NULL? NULL: result;
}
export("main")
int main(){
char *result;
for(int i= 0; i<BENCH_ITERATIONS; i++){
result = get_key_value(0);
//printf("getting index 0 is %s\n", result);
free(result);
}
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#define import(name) __attribute__((import_name(name)))
#define export(name) __attribute__((export_name(name))) __attribute__((visibility("default")))
char *shared_mem=NULL;
import("get_key_value")
extern int get_key_value(int index);
import("set_key_value")
extern void set_key_value(int index, char *value);
export("init_shared_mem")
char *init_shared_mem(int size){
if(size <= 0) return NULL;
shared_mem = (char*) malloc(size);
return shared_mem==NULL? NULL: shared_mem;
}
export("main")
int main(){
//set_key_value(0, "ok");
int value_length;
for(int i= 0; i<BENCH_ITERATIONS; i++){
value_length = get_key_value(0);
//printf("getting index 0 is %.*s\n", value_length, shared_mem);
}
return 0;
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment