Skip to content

Commit

Permalink
Limit the memory usage of block and block IR
Browse files Browse the repository at this point in the history
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  |
  • Loading branch information
qwe661234 committed Sep 27, 2023
1 parent 806fc6e commit 38d663d
Show file tree
Hide file tree
Showing 4 changed files with 25 additions and 15 deletions.
13 changes: 7 additions & 6 deletions src/emulate.c
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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);
Expand Down
20 changes: 13 additions & 7 deletions src/riscv.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@
#include <stdlib.h>
#include <string.h>

#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)
{
Expand All @@ -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++) {
Expand All @@ -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;
Expand Down Expand Up @@ -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);
Expand All @@ -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);
}
Expand Down
3 changes: 3 additions & 0 deletions src/riscv.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */ \
Expand Down
4 changes: 2 additions & 2 deletions src/riscv_private.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down Expand Up @@ -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;
};
Expand Down

1 comment on commit 38d663d

@jserv
Copy link
Contributor

@jserv jserv commented on 38d663d Sep 27, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Benchmarks

Benchmark suite Current: 38d663d Previous: 7df12b1 Ratio
Dhrystone 1084.62 Average DMIPS over 10 runs 1246.66 Average DMIPS over 10 runs 1.15
Coremark 1010.928 Average iterations/sec over 10 runs 1102.866 Average iterations/sec over 10 runs 1.09

This comment was automatically generated by workflow using github-action-benchmark.

Please sign in to comment.