diff --git a/chapters/05_experiment_setup/05_01_execution_environment.tex b/chapters/05_experiment_setup/05_01_execution_environment.tex index 12f137c..e309a81 100644 --- a/chapters/05_experiment_setup/05_01_execution_environment.tex +++ b/chapters/05_experiment_setup/05_01_execution_environment.tex @@ -14,8 +14,8 @@ While a suitable and correctly configured statically linked real-time operating Instead, experiments are cross-compiled to freestanding executables using \code{i386-elf-gcc} with Newlib\footnote{\url[2026-08-12]{https://sourceware.org/newlib/}} libc. To make Newlib work inside a bare-metal environment, certain system calls must be provided by the platform, although not all of them need to be functional\footnote{\url[2026-08-12]{https://sourceware.org/newlib/libgloss.html\#Libraries-1}}: \begin{itemize} - \item \code{sbrk()} is required for Newlib's \code{malloc()}, \code{calloc()} and \code{realloc()} memory-management functions. Although \Gls{wamr} uses its own memory allocator implementation (see \autoref{sec:wasmhostprogram}), \Gls{wasm} targets may still require a functional \code{sbrk()} if \Gls{wamr}'s \code{snprintf}/\code{vsnprintf} are used, depending on the format string. - \item \code{read()}, \code{write()}, \code{close()}, \code{fstat()} and \code{isatty()} stubs are required for \Gls{wamr} targets. Since no filesystem or console exists in the execution environment, they do not need to be functional. + \item \code{sbrk()} is required for Newlib's \code{malloc()}, \code{calloc()} and \code{realloc()} memory-management functions. Although \Gls{wamr} uses its own memory allocator implementation (see \autoref{sssec:wamrmemoryallocation}), \Gls{wasm} targets may still require a functional \code{sbrk()} if \Gls{wamr}'s \code{snprintf}/\code{vsnprintf} are used, depending on the format string. + \item \code{read()}, \code{write()}, \code{close()}, \code{fstat()} and \code{isatty()} stubs are required for \Gls{wamr} targets. Since no filesystem or console exists in the execution environment, they do not need to implement functional behavior. \item \code{lseek()} is required for C and \Gls{wamr} targets. A stub suffices for the same reason as above. \item \code{\_exit()}, \code{kill()} and \code{getpid()} are required for \Gls{wamr} targets. Implementations can be omitted, as the execution environment does not use processes. \end{itemize} diff --git a/chapters/05_experiment_setup/05_02_wamr_modifications.tex b/chapters/05_experiment_setup/05_02_wamr_modifications.tex index cc7282e..da310dd 100644 --- a/chapters/05_experiment_setup/05_02_wamr_modifications.tex +++ b/chapters/05_experiment_setup/05_02_wamr_modifications.tex @@ -4,7 +4,7 @@ \begin{document} -\section{\Gls{wamr} Modifications}\label{sec:wamrmodifications} +\section{WAMR Modifications}\label{sec:wamrmodifications} The experiments use a slightly modified version of \Gls{wamr} based on release 2.4.4\footnote{\url[2026-09-11]{https://github.com/wasm-micro-runtime/wasm-micro-runtime/releases/tag/WAMR-2.4.4}}. The modifications provide a platform port for the bare-metal execution environment described in \autoref{sec:executionenvironment} and an explicit marker call during runtime exceptions. @@ -15,14 +15,14 @@ The modifications provide a platform port for the bare-metal execution environme The added \code{baremetal} platform only provides the subset of this layer that is required by the experiments. It is selected through \code{WAMR\_BUILD\_PLATFORM=baremetal} and compiled for 32-bit x86 using a freestanding cross-compiler. The build enables the classic interpreter and \Gls{aot} execution, while disabling the fast interpreter, the \Glspl{jit}, and WASI support. -The modifications also remove the mandatory CMake thread-library lookup and disables the compiler option \code{-mindirect-branch-register}\todo{Option was disabled because gcc 5.4 didn't support it, now I'm using a newer cross compiler}. +The modifications also remove the mandatory CMake thread-library lookup and disable the compiler option \code{-mindirect-branch-register}\todo{Option was disabled because gcc 5.4 didn't support it, now I'm using a newer cross compiler}. Since execution is single-threaded and no operating system is present, many platform functions are stubs. Platform initialization and mutex operations report success without performing any work, console output is discarded, and time queries return zero. The system allocation functions \code{os\_malloc} and \code{os\_realloc} return \code{NULL}. Instead, the host initializes \Gls{wamr} with a supplied memory pool or custom allocation callbacks, as described later in \autoref{sssec:wamrmemoryallocation}. -\Gls{aot} experiment variants additionally require implementations of \code{os\_mmap} and \code{os\_mremap}, to allocate memory for the loaded module text. +\Gls{aot} experiment variants also require implementations of \code{os\_mmap} and \code{os\_mremap} to allocate memory for the loaded module text. The platform provides these using a static \SI{2}{\mega\byte} buffer and a simple bump allocator (allocator with monotonically increasing offset into the reserved memory region). Remapping allocates a new region and copies the old one, without reclaiming any memory. Unmapping does not reclaim memory, and \code{os\_mprotect} reports success without changing access permissions. diff --git a/chapters/05_experiment_setup/05_03_workload_structure.tex b/chapters/05_experiment_setup/05_03_workload_structure.tex index 105ecb2..1b9b39d 100644 --- a/chapters/05_experiment_setup/05_03_workload_structure.tex +++ b/chapters/05_experiment_setup/05_03_workload_structure.tex @@ -8,15 +8,15 @@ \subsection{Shared Traced Region}\label{ssec:sharedtracedregion} -All experiment variants (C, \Gls{aot} and interpreted) share the same traced region that contains the actual benchmarked workload. +All experiment variants (C, \Gls{aot} and interpreted) share the same traced region on the source level that contains the actual benchmarked workload. It is structured into three parts, the benchmark initialization, its execution and the success condition. -Initialization and success condition lie outside the traced region (see \autoref{lst:workloadstructure}), so a workload under fault always starts with its intended initial state and its result is always evaluated correctly. +Initialization and success condition lie outside the traced region (see \autoref{lst:workloadstructure}), so a workload under fault always starts with its intended initial state and its result evaluation is trustworthy. \begin{codeblock}[label=lst:workloadstructure]{Example of a shared workload.}{C++} \inputminted{cpp}{listings/workloadstructure.cpp} \end{codeblock} -The \code{EXPORT("fnct")} annotation expands to \code{\_\_attribute\_\_((export\_name("fnct")))}, a directive to the LLVM-based C-to-\Gls{wasm} compiler from the WASI SDK\footnote{\url[2026-09-11]{https://github.com/WebAssembly/wasi-sdk}} that controls the name of the exported \Gls{wasm} module. +The \code{EXPORT("fnct")} annotation expands to \code{\_\_attribute\_\_((export\_name("fnct")))}, a directive to the LLVM-based C-to-\Gls{wasm} compiler from the WASI SDK\footnote{\url[2026-09-11]{https://github.com/WebAssembly/wasi-sdk}} that controls the name of the exported \Gls{wasm} function, so it can later be found by \Gls{wamr} (see \autoref{sssec:wamrmoduleexecution}). Such a shared workload is then called from a variant-specific host program, as seen in the next two sections. @@ -31,14 +31,15 @@ The \code{MAIN} and \code{RET} macros expand according to the appropriate entry \inputminted{cpp}{listings/nativehost.cpp} \end{codeblock} -\subsection{\Gls{wasm} Host and \Gls{wamr} Setup}\label{ssec:wasmhostandwamrsetup} +\subsection{Wasm Host and WAMR Setup}\label{ssec:wasmhostandwamrsetup} The host program for \Gls{wasm} experiment variants needs to do a lot of additional work compared to the native one, mainly concerning the initialization of the \Gls{wamr} runtime\footnote{Described here: \url[2026-09-11]{https://wasmruntime.com/en/tutorials/wamr\#34-step-4-c-embedding-integration}}. \subsubsection{Runtime Initialization and Memory Allocation}\label{sssec:wamrmemoryallocation} -\Gls{wamr} supports two different allocators for the \Gls{wasm} runtime memory: \code{Alloc\_With\_Pool} and \code{Alloc\_With\_Allocator}. -\code{Alloc\_With\_Pool} is the simplest one, as it only requires a memory pool and no custom allocator functions. +\Gls{wamr} supports different allocators for the \Gls{wasm} runtime memory. +Relevant for this thesis are \code{Alloc\_With\_Pool} and \code{Alloc\_With\_Allocator}. +\code{Alloc\_With\_Pool} is the simplest one, as it only requires a memory pool, no custom allocator functions. \code{Alloc\_With\_Allocator} is slightly more involved, as it allows complete control over memory regions and allocation behavior by utilizing custom allocator functions. To use this allocator, \code{malloc}, \code{realloc} and \code{free} need to be implemented. In this thesis, a simple bump allocator is implemented, like the one used by \Gls{wamr} itself, described in \autoref{ssec:wamrbaremetal} @@ -73,7 +74,7 @@ This indirection happens implicitly, on the application level no special steps n To be compatible with the native function registration mechanism, functions need to accept the \Gls{wasm} execution environment as an argument (see \autoref{lst:wamrnativefunctions}). -\subsubsection{\Gls{wasm} Module Instantiation and Execution}\label{sssec:wamrmoduleexecution} +\subsubsection{Wasm Module Instantiation and Execution}\label{sssec:wamrmoduleexecution} To load the workload's \Gls{wasm} module and run it, a series of steps need to be executed: \begin{enumerate} diff --git a/chapters/05_experiment_setup/05_04_experiment_variants.tex b/chapters/05_experiment_setup/05_04_experiment_variants.tex index 7da7237..f1f22e0 100644 --- a/chapters/05_experiment_setup/05_04_experiment_variants.tex +++ b/chapters/05_experiment_setup/05_04_experiment_variants.tex @@ -10,6 +10,10 @@ \item C only \item WAMR AOT \item WAMR interpreter + \item Different filters + \item Compiler settings, optimization settings (add tables to the appendix that include EVERY setting) + \item Memory sizes + \item Runner settings, timeout size \end{itemize} \end{document} diff --git a/chapters/05_experiment_setup/listings/wamrinitialization.cpp b/chapters/05_experiment_setup/listings/wamrinitialization.cpp index a2c42b4..1ce46d9 100644 --- a/chapters/05_experiment_setup/listings/wamrinitialization.cpp +++ b/chapters/05_experiment_setup/listings/wamrinitialization.cpp @@ -1,16 +1,16 @@ static RuntimeInitArgs init_args; memset(&init_args, 0, sizeof(RuntimeInitArgs)); -// If using Alloc_With_Allocator: +#ifdef ALLOC_WITH_ALLOCATOR init_args.mem_alloc_type = Alloc_With_Allocator; init_args.mem_alloc_option.allocator.malloc_func = (void *)wamr_malloc; init_args.mem_alloc_option.allocator.realloc_func = (void *)wamr_realloc; init_args.mem_alloc_option.allocator.free_func = (void *)wamr_free; - -// If using Alloc_With_Pool instead: +#else // Alloc_With_Pool init_args.mem_alloc_type = Alloc_With_Pool; init_args.mem_alloc_option.pool.heap_buf = global_heap_buf; init_args.mem_alloc_option.pool.heap_size = sizeof(global_heap_buf); +#endif init_args.max_thread_num = 1; if (!wasm_runtime_full_init(&init_args)) {