From 38d663d89fabe54c2a971a49454bf7cc969eea03 Mon Sep 17 00:00:00 2001 From: Yen-Fu Chen Date: Wed, 27 Sep 2023 19:52:34 +0800 Subject: [PATCH] Limit the memory usage of block and block IR Originally, memory usage sharply increased during the frequent allocation and freeing of basic blocks and IR arrays. To reduce memory usage, we introduced a block memory pool and an IR array memory pool. As shown in the analysis below, we experienced about a 10% performance loss due to the reduction in memory usage. However, we are currently utilizing KiB of memory instead of MiB. * Performance | Metric | Original | Proposed | |----------+-----------------+-----------------| | Dhrystone| 2359 DMIPS | 2085.5 DMIPS | | CoreMark | 1967.382 iter/s | 1823.333 iter/s | * Memory usage | Metric | Original | Proposed | |----------+----------+----------| | Dhrystone| 99 MiB | 169 KiB | | CoreMark | 2.4 MiB | 176 KiB | --- src/emulate.c | 13 +++++++------ src/riscv.c | 20 +++++++++++++------- src/riscv.h | 3 +++ src/riscv_private.h | 4 ++-- 4 files changed, 25 insertions(+), 15 deletions(-) diff --git a/src/emulate.c b/src/emulate.c index 872e6b0c1..3148e4fa2 100644 --- a/src/emulate.c +++ b/src/emulate.c @@ -30,6 +30,7 @@ extern struct target_ops gdbstub_ops; #endif #include "decode.h" +#include "mpool.h" #include "riscv.h" #include "riscv_private.h" #include "state.h" @@ -278,14 +279,14 @@ static inline uint32_t hash(size_t k) } /* allocate a basic block */ -static block_t *block_alloc(const uint8_t bits) +static block_t *block_alloc(riscv_t *rv) { - block_t *block = malloc(sizeof(struct block)); + block_t *block = mpool_alloc(rv->block_mp); assert(block); - block->insn_capacity = 1 << bits; + block->insn_capacity = 1 << BLOCK_CAPACITY_BITS; block->n_insn = 0; block->predict = NULL; - block->ir = malloc(block->insn_capacity * sizeof(rv_insn_t)); + block->ir = mpool_alloc(rv->block_ir_mp); assert(block->ir); return block; } @@ -1009,12 +1010,12 @@ static block_t *block_find_or_translate(riscv_t *rv) if (!next) { if (map->size * 1.25 > map->block_capacity) { - block_map_clear(map); + block_map_clear(rv, map); prev = NULL; } /* allocate a new block */ - next = block_alloc(10); + next = block_alloc(rv); /* translate the basic block */ block_translate(rv, next); diff --git a/src/riscv.c b/src/riscv.c index d5822d5e9..0d28ebb7a 100644 --- a/src/riscv.c +++ b/src/riscv.c @@ -7,9 +7,9 @@ #include #include +#include "mpool.h" #include "riscv_private.h" #include "state.h" - /* initialize the block map */ static void block_map_init(block_map_t *map, const uint8_t bits) { @@ -19,7 +19,7 @@ static void block_map_init(block_map_t *map, const uint8_t bits) } /* clear all block in the block map */ -void block_map_clear(block_map_t *map) +void block_map_clear(riscv_t *rv, block_map_t *map) { assert(map); for (uint32_t i = 0; i < map->block_capacity; i++) { @@ -28,8 +28,8 @@ void block_map_clear(block_map_t *map) continue; for (uint32_t i = 0; i < block->n_insn; i++) free(block->ir[i].fuse); - free(block->ir); - free(block); + mpool_free(rv->block_ir_mp, block->ir); + mpool_free(rv->block_mp, block); map->map[i] = NULL; } map->size = 0; @@ -92,11 +92,15 @@ riscv_t *rv_create(const riscv_io_t *io, /* copy over the userdata */ rv->userdata = userdata; - + rv->block_mp = mpool_create(sizeof(block_t) << BLOCK_MAP_CAPACITY_BITS, + sizeof(block_t)); + rv->block_ir_mp = mpool_create( + sizeof(rv_insn_t) << (BLOCK_MAP_CAPACITY_BITS + BLOCK_CAPACITY_BITS), + sizeof(rv_insn_t) << BLOCK_CAPACITY_BITS); rv->output_exit_code = output_exit_code; /* initialize the block map */ - block_map_init(&rv->block_map, 10); + block_map_init(&rv->block_map, BLOCK_MAP_CAPACITY_BITS); /* reset */ rv_reset(rv, 0U, argc, args); @@ -122,7 +126,9 @@ bool rv_enables_to_output_exit_code(riscv_t *rv) void rv_delete(riscv_t *rv) { assert(rv); - block_map_clear(&rv->block_map); + block_map_clear(rv, &rv->block_map); + mpool_destroy(rv->block_mp); + mpool_destroy(rv->block_ir_mp); free(rv->block_map.map); free(rv); } diff --git a/src/riscv.h b/src/riscv.h index 992751cf3..138146224 100644 --- a/src/riscv.h +++ b/src/riscv.h @@ -11,6 +11,9 @@ extern "C" { #endif +#define BLOCK_MAP_CAPACITY_BITS 10 +#define BLOCK_CAPACITY_BITS 10 + #define RV_REGS_LIST \ _(zero) /* hard-wired zero, ignoring any writes */ \ _(ra) /* return address */ \ diff --git a/src/riscv_private.h b/src/riscv_private.h index d608b338f..7090c8119 100644 --- a/src/riscv_private.h +++ b/src/riscv_private.h @@ -68,7 +68,7 @@ typedef struct { } block_map_t; /* clear all block in the block map */ -void block_map_clear(block_map_t *map); +void block_map_clear(riscv_t *rv, block_map_t *map); struct riscv_internal { bool halt; /* indicate whether the core is halted */ @@ -121,7 +121,7 @@ struct riscv_internal { bool compressed; /**< current instruction is compressed or not */ block_map_t block_map; /**< basic block map */ - + struct mpool *block_mp, *block_ir_mp; /* print exit code on syscall_exit */ bool output_exit_code; };