@samitouri / QOSamiQemu / commits / a4e85f89e8

memory: Optimize flatview_simplify() to eliminate redundant memmove calls

The original flatview_simplify() implementation uses memmove() to shift array elements after each merge operation, resulting in O(n²) time complexity in the worst case. This is inefficient for VMs with large memory topologies containing hundreds of MemoryRegions. Replace the memmove-based approach with a two-pointer in-place compression algorithm that achieves O(n) time complexity. The new algorithm uses a write pointer i and a read pointer j, where i ≤ j is always maintained. This invariant ensures we never overwrite unprocessed data, making memmove unnecessary. Signed-off-by: Bin Guo <guobin@linux.alibaba.com> Link: https://lore.kernel.org/r/20260331060731.82641-1-guobin@linux.alibaba.com Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>

Bin Guo committed Mar 31, 2026 at 14:07 UTC a4e85f89e8c765ea5d425651741ac1e6d510b70d
1 file changed +14 -13
system/memory.c
+14 -13
@@ -336,24 +336,25 @@ static bool can_merge(FlatRange *r1, FlatRange *r2)
336 /* Attempt to simplify a view by merging adjacent ranges */
337 static void flatview_simplify(FlatView *view)
338 {
339 - unsigned i, j, k;
339 + unsigned i, j;
340 +
341 + if (view->nr <= 1) {
342 + return;
343 + }
344
345 i = 0;
342 - while (i < view->nr) {
343 - j = i + 1;
344 - while (j < view->nr
345 - && can_merge(&view->ranges[j-1], &view->ranges[j])) {
346 + for (j = 1; j < view->nr; j++) {
347 + if (can_merge(&view->ranges[i], &view->ranges[j])) {
348 int128_addto(&view->ranges[i].addr.size, view->ranges[j].addr.size);
347 - ++j;
348 - }
349 - ++i;
350 - for (k = i; k < j; k++) {
351 - memory_region_unref(view->ranges[k].mr);
349 + memory_region_unref(view->ranges[j].mr);
350 + } else {
351 + i++;
352 + if (i != j) {
353 + view->ranges[i] = view->ranges[j];
354 + }
355 }
353 - memmove(&view->ranges[i], &view->ranges[j],
354 - (view->nr - j) * sizeof(view->ranges[j]));
355 - view->nr -= j - i;
356 }
357 + view->nr = i + 1;
358 }
359
360 static void adjust_endianness(MemoryRegion *mr, uint64_t *data, MemOp op)