find_ram_offset optimization

The ram_offset allocator searches the smalest gap in the ram_offset address space.
This is slow especialy in combination with many allocation (i.e. snapshots). When
it is known that there is no gap, this is now optimized.
This commit is contained in:
Takacs, Philipp 2023-02-28 16:09:45 +01:00
parent 550265f3c1
commit e54cf7ee03
2 changed files with 21 additions and 0 deletions

View File

@ -41,6 +41,7 @@ typedef struct {
// This struct is originally from qemu/include/exec/ramlist.h
typedef struct RAMList {
bool freed;
RAMBlock *mru_block;
QLIST_HEAD(, RAMBlock) blocks;
} RAMList;

View File

@ -955,6 +955,21 @@ void flatview_add_to_dispatch(struct uc_struct *uc, FlatView *fv, MemoryRegionSe
register_subpage(uc, fv, &remain);
}
static ram_addr_t find_ram_offset_last(struct uc_struct *uc, ram_addr_t size)
{
RAMBlock *block;
ram_addr_t result = 0;
RAMBLOCK_FOREACH(block) {
result = MAX(block->offset + block->max_length, result);
}
if (result + size > RAM_ADDR_MAX) {
abort();
}
return result;
}
/* Allocate space within the ram_addr_t space that governs the
* dirty bitmaps.
* Called with the ramlist lock held.
@ -970,6 +985,10 @@ static ram_addr_t find_ram_offset(struct uc_struct *uc, ram_addr_t size)
return 0;
}
if (!uc->ram_list.freed) {
return find_ram_offset_last(uc, size);
}
RAMBLOCK_FOREACH(block) {
ram_addr_t candidate, next = RAM_ADDR_MAX;
@ -1145,6 +1164,7 @@ void qemu_ram_free(struct uc_struct *uc, RAMBlock *block)
QLIST_REMOVE_RCU(block, next);
uc->ram_list.mru_block = NULL;
uc->ram_list.freed = true;
/* Write list before version */
//smp_wmb();
// call_rcu(block, reclaim_ramblock, rcu);