Browse Source

Add gc performance profiling (#2716)

Use `cmake -DWAMR_BUILD_GC_PERF_PROFILING=1` to enable it.
WenLY1 2 năm trước cách đây
mục cha
commit
6d92534c7f

+ 6 - 0
build-scripts/config_common.cmake

@@ -331,6 +331,12 @@ if (WAMR_BUILD_GC EQUAL 1)
     message("      GC testing enabled")
   endif()
 endif ()
+if (WAMR_BUILD_GC EQUAL 1 AND WAMR_BUILD_GC_PERF_PROFILING EQUAL 1)
+  add_definitions (-DWASM_ENABLE_GC_PERF_PROFILING=1)
+  message ("     GC performance profiling enabled")
+else ()
+  message ("     GC performance profiling disabled")
+endif ()
 if (WAMR_BUILD_GC_BINARYEN EQUAL 1)
   add_definitions (-DWASM_ENABLE_GC_BINARYEN=1)
   message ("     GC binaryen compatible mode on")

+ 5 - 0
core/config.h

@@ -290,6 +290,11 @@
 #define WASM_ENABLE_SIMD 0
 #endif
 
+/* GC performance profiling */
+#ifndef WASM_ENABLE_GC_PERF_PROFILING
+#define WASM_ENABLE_GC_PERF_PROFILING 0
+#endif
+
 /* Memory profiling */
 #ifndef WASM_ENABLE_MEMORY_PROFILING
 #define WASM_ENABLE_MEMORY_PROFILING 0

+ 13 - 0
core/iwasm/common/wasm_application.c

@@ -18,6 +18,9 @@
 #if WASM_ENABLE_STRINGREF != 0
 #include "string_object.h"
 #endif
+#if WASM_ENABLE_GC_PERF_PROFILING != 0
+#include "../../shared/mem-alloc/mem_alloc.h"
+#endif
 #endif
 
 static void
@@ -250,6 +253,11 @@ wasm_application_execute_main(WASMModuleInstanceCommon *module_inst, int32 argc,
     }
 #endif
 
+#if WASM_ENABLE_GC_PERF_PROFILING != 0
+    void *handle = wasm_runtime_get_gc_heap_handle(module_inst);
+    mem_allocator_dump_perf_profiling(handle);
+#endif
+
 #if WASM_ENABLE_PERF_PROFILING != 0
     wasm_runtime_dump_perf_profiling(module_inst);
 #endif
@@ -816,6 +824,11 @@ wasm_application_execute_func(WASMModuleInstanceCommon *module_inst,
     }
 #endif
 
+#if WASM_ENABLE_GC_PERF_PROFILING != 0
+    void *handle = wasm_runtime_get_gc_heap_handle(module_inst);
+    mem_allocator_dump_perf_profiling(handle);
+#endif
+
 #if WASM_ENABLE_PERF_PROFILING != 0
     wasm_runtime_dump_perf_profiling(module_inst);
 #endif

+ 13 - 0
core/shared/mem-alloc/ems/ems_alloc.c

@@ -445,12 +445,25 @@ static int
 do_gc_heap(gc_heap_t *heap)
 {
     int ret = GC_SUCCESS;
+#if WASM_ENABLE_GC_PERF_PROFILING != 0
+    uint64 start = 0, end = 0, time = 0;
 
+    start = os_time_get_boot_microsecond();
+#endif
     if (heap->is_reclaim_enabled) {
         UNLOCK_HEAP(heap);
         ret = gci_gc_heap(heap);
         LOCK_HEAP(heap);
     }
+#if WASM_ENABLE_GC_PERF_PROFILING != 0
+    end = os_time_get_boot_microsecond();
+    time = end - start;
+    heap->total_gc_time += time;
+    if (time > heap->max_gc_time) {
+        heap->max_gc_time = time;
+    }
+    heap->total_gc_count += 1;
+#endif
     return ret;
 }
 #endif

+ 1 - 1
core/shared/mem-alloc/ems/ems_gc.c

@@ -143,8 +143,8 @@ sweep_instance_heap(gc_heap_t *heap)
     if ((heap->current_size - tot_free) > heap->highmark_size)
         heap->highmark_size = heap->current_size - tot_free;
 
-    gc_update_threshold(heap);
 #endif
+    gc_update_threshold(heap);
 }
 
 /**

+ 5 - 0
core/shared/mem-alloc/ems/ems_gc.h

@@ -333,6 +333,11 @@ gc_show_stat(gc_handle_t handle);
 #if WASM_ENABLE_GC != 0
 void
 gc_show_fragment(gc_handle_t handle);
+
+#if WASM_ENABLE_GC_PERF_PROFILING != 0
+void
+gc_dump_perf_profiling(gc_handle_t *handle);
+#endif
 #endif
 
 #ifdef __cplusplus

+ 1 - 0
core/shared/mem-alloc/ems/ems_gc_internal.h

@@ -311,6 +311,7 @@ typedef struct gc_heap_struct {
     gc_size_t gc_threshold_factor;
     gc_size_t total_gc_count;
     gc_size_t total_gc_time;
+    gc_size_t max_gc_time;
     /* Usually there won't be too many extra info node, so we try to use a fixed
      * array to store them, if the fixed array don't have enough space to store
      * the nodes, a new space will be allocated from heap */

+ 17 - 0
core/shared/mem-alloc/ems/ems_kfc.c

@@ -492,4 +492,21 @@ gc_show_fragment(void *heap_arg)
     os_printf("\n[GC %p top sizes] %" PRIu32 " %" PRIu32 " %" PRIu32 "\n", heap,
               stats[0], stats[1], stats[2]);
 }
+
+#if WASM_ENABLE_GC_PERF_PROFILING != 0
+void
+gc_dump_perf_profiling(gc_handle_t *handle)
+{
+    gc_heap_t *gc_heap_handle = (void *)handle;
+    if (gc_heap_handle) {
+        os_printf("\nGC performance summary\n");
+        os_printf("    Total GC time (ms): %u\n",
+                  gc_heap_handle->total_gc_time);
+        os_printf("    Max GC time (ms): %u\n", gc_heap_handle->max_gc_time);
+    }
+    else {
+        os_printf("Failed to dump GC performance\n");
+    }
+}
+#endif
 #endif

+ 9 - 0
core/shared/mem-alloc/mem_alloc.c

@@ -127,6 +127,15 @@ mem_allocator_unset_gc_finalizer(mem_allocator_t allocator, void *obj)
 {
     gc_unset_finalizer((gc_handle_t)allocator, (gc_object_t)obj);
 }
+
+#if WASM_ENABLE_GC_PERF_PROFILING != 0
+void
+mem_allocator_dump_perf_profiling(mem_allocator_t allocator)
+{
+    gc_dump_perf_profiling((gc_handle_t)allocator);
+}
+#endif
+
 #endif
 
 #else /* else of DEFAULT_MEM_ALLOCATOR */

+ 5 - 0
core/shared/mem-alloc/mem_alloc.h

@@ -76,6 +76,11 @@ mem_allocator_set_gc_finalizer(mem_allocator_t allocator, void *obj,
 
 void
 mem_allocator_unset_gc_finalizer(mem_allocator_t allocator, void *obj);
+
+#if WASM_ENABLE_GC_PERF_PROFILING != 0
+void
+mem_allocator_dump_perf_profiling(mem_allocator_t allocator);
+#endif
 #endif /* end of WASM_ENABLE_GC != 0 */
 
 bool

+ 6 - 0
product-mini/platforms/nuttx/wamr.mk

@@ -217,6 +217,12 @@ else
 CFLAGS += -DWASM_ENABLE_PERF_PROFILING=0
 endif
 
+ifeq ($(CONFIG_INTERPRETERS_WAMR_GC_PERF_PROFILING),y)
+CFLAGS += -DWASM_ENABLE_GC_PERF_PROFILING=1
+else
+CFLAGS += -DWASM_ENABLE_GC_PERF_PROFILING=0
+endif
+
 ifeq ($(CONFIG_INTERPRETERS_WAMR_MEMORY_PROFILING),y)
 CFLAGS += -DWASM_ENABLE_MEMORY_PROFILING=1
 else