diff --git a/src/backend/V8Engine.cpp b/src/backend/V8Engine.cpp index 0fdea113..72e2e739 100644 --- a/src/backend/V8Engine.cpp +++ b/src/backend/V8Engine.cpp @@ -277,6 +277,17 @@ void m::wasm::detail::print(const v8::FunctionCallbackInfo &info) std::cout << std::endl; } +void m::wasm::detail::print_memory_consumption(const v8::FunctionCallbackInfo &info) +{ + M_insist(Options::Get().statistics); + + auto alloc_total_mem = info[0].As()->Value(); + auto alloc_peak_mem = info[1].As()->Value(); + + std::cout << "Allocated memory overall consumption: " << alloc_total_mem / (1024.0 * 1024.0) << " MiB"<< std::endl; + std::cout << "Allocated memory peak consumption: " << alloc_peak_mem / (1024.0 * 1024.0) << " MiB"<< std::endl; +} + void m::wasm::detail::set_wasm_instance_raw_memory(const v8::FunctionCallbackInfo &info) { v8::Local wasm_instance = info[0].As(); @@ -728,6 +739,7 @@ void V8Engine::compile(const m::MatchBase &plan) const #if 1 /*----- Add print function. --------------------------------------------------------------------------------------*/ Module::Get().emit_function_import("print"); + Module::Get().emit_function_import("print_memory_consumption"); #endif /*----- Emit code for run function which computes the last pipeline and calls other pipeline functions. ----------*/ @@ -743,6 +755,14 @@ void V8Engine::compile(const m::MatchBase &plan) const { auto S = CodeGenContext::Get().scoped_environment(); // create scoped environment for this function run(); // call run function + if (Options::Get().statistics) { + std::cout << "Pre-allocated memory overall consumption: " + << Module::Allocator().pre_allocated_memory_consumption() / (1024.0 * 1024.0) + << " MiB" << std::endl; + Module::Get().emit_call("print_memory_consumption", + Module::Allocator().allocated_memory_consumption(), + Module::Allocator().allocated_memory_peak()); + } main.emit_return(CodeGenContext::Get().num_tuples()); // return size of result set } @@ -1029,6 +1049,7 @@ v8::Local m::wasm::detail::create_env(v8::Isolate &isolate, const m: } ADD_FUNC(insist) ADD_FUNC(print) + ADD_FUNC(print_memory_consumption) ADD_FUNC(read_result_set) #undef ADD_FUNC { diff --git a/src/backend/V8Engine.hpp b/src/backend/V8Engine.hpp index 3357239a..615bf236 100644 --- a/src/backend/V8Engine.hpp +++ b/src/backend/V8Engine.hpp @@ -80,6 +80,7 @@ struct V8InspectorClientImpl : v8_inspector::V8InspectorClient void insist(const v8::FunctionCallbackInfo &info); void _throw(const v8::FunctionCallbackInfo &info); void print(const v8::FunctionCallbackInfo &info); +void print_memory_consumption(const v8::FunctionCallbackInfo &info); void set_wasm_instance_raw_memory(const v8::FunctionCallbackInfo &info); void read_result_set(const v8::FunctionCallbackInfo &info); diff --git a/src/backend/WasmDSL.cpp b/src/backend/WasmDSL.cpp index f771fbe3..8a531da5 100644 --- a/src/backend/WasmDSL.cpp +++ b/src/backend/WasmDSL.cpp @@ -220,6 +220,12 @@ struct LinearAllocator : Allocator uint32_t pre_alloc_addr_; ///> runtime global size of the currently used memory, used as pointer to next free allocation Global alloc_addr_; + ///> compile-time total memory consumption + uint32_t pre_alloc_total_mem_ = 0; + ///> runtime total memory consumption + Global alloc_total_mem_; + ///> runtime peak memory consumption + Global alloc_peak_mem_; public: LinearAllocator(const memory::AddressSpace &memory, uint32_t start_addr) @@ -229,6 +235,8 @@ struct LinearAllocator : Allocator M_insist(start_addr != 0, "memory address 0 is reserved as `nullptr`"); #ifdef M_ENABLE_SANITY_FIELDS alloc_addr_.val().discard(); // artificial use of `alloc_addr_` to silence diagnostics if allocator is not used + alloc_total_mem_.val().discard(); // artificial use of `alloc_total_mem_` to silence diagnostics if allocator is not used + alloc_peak_mem_.val().discard(); // artificial use of `alloc_peak_mem_` to silence diagnostics if allocator is not used #endif } @@ -245,6 +253,7 @@ struct LinearAllocator : Allocator align_pre_memory(alignment); void *ptr = static_cast(memory_.addr()) + pre_alloc_addr_; pre_alloc_addr_ += bytes; // advance memory size by bytes + pre_alloc_total_mem_ += bytes; M_insist(memory_.size() >= pre_alloc_addr_, "allocation must fit in memory"); return ptr; } @@ -257,6 +266,7 @@ struct LinearAllocator : Allocator align_pre_memory(alignment); Ptr ptr(U32x1(pre_alloc_addr_).template to()); pre_alloc_addr_ += bytes; // advance memory size by bytes + pre_alloc_total_mem_ += bytes; M_insist(memory_.size() >= pre_alloc_addr_, "allocation must fit in memory"); return ptr; } @@ -266,7 +276,9 @@ struct LinearAllocator : Allocator if (alignment != 1U) align_memory(alignment); Var> ptr(alloc_addr_.template to()); - alloc_addr_ += bytes; // advance memory size by bytes + alloc_addr_ += bytes.clone(); // advance memory size by bytes + alloc_total_mem_ += bytes; + alloc_peak_mem_ = Select(alloc_peak_mem_ > alloc_addr_, alloc_peak_mem_, alloc_addr_); Wasm_insist(memory_.size() >= alloc_addr_, "allocation must fit in memory"); return ptr; } @@ -285,6 +297,10 @@ struct LinearAllocator : Allocator pre_allocations_performed_ = true; } + uint32_t pre_allocated_memory_consumption() const override { return pre_alloc_total_mem_; } + U32x1 allocated_memory_consumption() const override { return alloc_total_mem_; } + U32x1 allocated_memory_peak() const override { return alloc_peak_mem_; } + private: /** Aligns the memory for pre-allocations with alignment requirement `align`. */ void align_pre_memory(uint32_t alignment) { diff --git a/src/backend/WasmDSL.hpp b/src/backend/WasmDSL.hpp index 30f3339d..6ece9926 100644 --- a/src/backend/WasmDSL.hpp +++ b/src/backend/WasmDSL.hpp @@ -6490,6 +6490,13 @@ struct Allocator * requested. */ virtual void perform_pre_allocations() = 0; + /** Returns the pre-allocated memory overall consumption. */ + virtual uint32_t pre_allocated_memory_consumption() const = 0; + /** Returns the allocated memory overall consumption. */ + virtual U32x1 allocated_memory_consumption() const = 0; + /** Returns the allocated memory peak consumption. */ + virtual U32x1 allocated_memory_peak() const = 0; + Var> allocate(uint32_t bytes, uint32_t align = 1) { return allocate(U32x1(bytes), align); } void deallocate(Ptr ptr, uint32_t bytes) { return deallocate(ptr, U32x1(bytes)); }