## 4 Results
### Garbage Collector Stress Testing  
Efficient memory management is critical in embedded system development, particularly when deploying a virtual machine (VM) on microcontrollers with constrained  
Figure 16: Comparison of the decompiled code for Lua 5.0 and Stella with loop instructions highlighted (authors’ contribution). hardware resources. Microcontrollers like NodeMCU ESP8266 have limited RAM and flash memory, presenting a unique challenge to developers who must optimize performance while ensuring system stability. The effective management of memory resources is essential, as this directly influences system responsiveness, reliability, and the ability to handle concurrent tasks or execute scripts efficiently. When a VM is implemented on a microcontroller, an additional layer of abstraction is introduced, complicating the memory allocation and deallocation processes. Unlike standard computing platforms, where memory resources are relatively abundant, embedded systems require the garbage collector to be highly efficient to prevent performance degradation. The demand for optimized garbage collection is especially pronounced during high-stakes scenarios, such as handling web server requests, performing firmware updates, or managing real-time operations. Any delay in garbage collection can lead to bottlenecks, increased latency, or even system failures if memory runs out during critical tasks [8]. Consequently, garbage collector stress tests are essential for evaluating the system's ability to efficiently manage memory allocation and deallocation under varying loads, simulating realistic conditions such as simultaneous web requests and VM operations. The performed stress test relies on allocation frequencies, sizes, and object retention times, defined using normal distribution and created for the VM instance as indicators for when a new object should be allocated, with byte number and the timestamp after which the object should be deleted by the GC. The mean value, standard deviation (sigma), and bounds are carefully defined to emulate typical allocation behaviours in an embedded environment. Specifically, the allocation frequency measured in seconds has a mean of 0.08 with a sigma of 0.03, without upper bounds, indicating a moderate allocation rate with some variability. Allocation sizes follow a distribution with a mean of 64 bytes and a sigma of 32 bytes, constrained by a minimum size of 16 bytes to reflect common memory usage patterns. The duration parameter, with a mean of 1 and a sigma of 2, has a minimum value of 0.1, simulating the typical retention time of allocated objects. During the tests, which ran for 20 min, the initial collection threshold was set at 1 KB. Memory allocation entries were imported as an array, where each entry created an instance of the \"AllocationEntry\" class. These instances were processed in the main loop using the integrated \"mills(0\" function. When the current time matched the allocation time, a new object with the specified size was allocated. The garbage collection mechanism, upon reaching the next collection threshold, performed a marking phase that only marked objects whose retention duration had not yet expired. Consequently, only expired objects were deallocated, optimizing the garbage collection process. The implementation in Figure 17 illustrates an approach more suitable for Linux-based systems using the \"timeval\" struct from the \"sys/time.h\" library. Figure 17: Object marking for time-constrained allocation entries. The results, as presented in Figures 18 and 19, indicate that the garbage collector handled a total of approximately 957 KB of memory with an allocation rate of around 798 bytes per second and a frequency of 25 objects per second. The modified algorithm demonstrated stable performance and maintained a steady memory footprint, averaging 8.639 KB of used heap memory.