From e54cf7ee036c0a888ae77832c3ca321ba0b42c5c Mon Sep 17 00:00:00 2001 From: "Takacs, Philipp" Date: Tue, 28 Feb 2023 16:09:45 +0100 Subject: [PATCH] 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. --- include/qemu.h | 1 + qemu/exec.c | 20 ++++++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/include/qemu.h b/include/qemu.h index 337f4f8f..8705a1a6 100644 --- a/include/qemu.h +++ b/include/qemu.h @@ -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; diff --git a/qemu/exec.c b/qemu/exec.c index 2a664788..af77e5de 100644 --- a/qemu/exec.c +++ b/qemu/exec.c @@ -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);