[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PULL 12/29] migration: savevm_state_handler_insert: constant-time eleme
From: |
Juan Quintela |
Subject: |
[PULL 12/29] migration: savevm_state_handler_insert: constant-time element insertion |
Date: |
Mon, 20 Jan 2020 11:33:23 +0100 |
From: Scott Cheloha <address@hidden>
savevm_state's SaveStateEntry TAILQ is a priority queue. Priority
sorting is maintained by searching from head to tail for a suitable
insertion spot. Insertion is thus an O(n) operation.
If we instead keep track of the head of each priority's subqueue
within that larger queue we can reduce this operation to O(1) time.
savevm_state_handler_remove() becomes slightly more complex to
accomodate these gains: we need to replace the head of a priority's
subqueue when removing it.
With O(1) insertion, booting VMs with many SaveStateEntry objects is
more plausible. For example, a ppc64 VM with maxmem=8T has 40000 such
objects to insert.
Signed-off-by: Scott Cheloha <address@hidden>
Reviewed-by: Dr. David Alan Gilbert <address@hidden>
Reviewed-by: Juan Quintela <address@hidden>
Signed-off-by: Juan Quintela <address@hidden>
---
migration/savevm.c | 26 +++++++++++++++++++++++---
1 file changed, 23 insertions(+), 3 deletions(-)
diff --git a/migration/savevm.c b/migration/savevm.c
index 30d980caa2..e57686bca7 100644
--- a/migration/savevm.c
+++ b/migration/savevm.c
@@ -250,6 +250,7 @@ typedef struct SaveStateEntry {
typedef struct SaveState {
QTAILQ_HEAD(, SaveStateEntry) handlers;
+ SaveStateEntry *handler_pri_head[MIG_PRI_MAX + 1];
int global_section_id;
uint32_t len;
const char *name;
@@ -261,6 +262,7 @@ typedef struct SaveState {
static SaveState savevm_state = {
.handlers = QTAILQ_HEAD_INITIALIZER(savevm_state.handlers),
+ .handler_pri_head = { [MIG_PRI_DEFAULT ... MIG_PRI_MAX] = NULL },
.global_section_id = 0,
};
@@ -709,24 +711,42 @@ static void savevm_state_handler_insert(SaveStateEntry
*nse)
{
MigrationPriority priority = save_state_priority(nse);
SaveStateEntry *se;
+ int i;
assert(priority <= MIG_PRI_MAX);
- QTAILQ_FOREACH(se, &savevm_state.handlers, entry) {
- if (save_state_priority(se) < priority) {
+ for (i = priority - 1; i >= 0; i--) {
+ se = savevm_state.handler_pri_head[i];
+ if (se != NULL) {
+ assert(save_state_priority(se) < priority);
break;
}
}
- if (se) {
+ if (i >= 0) {
QTAILQ_INSERT_BEFORE(se, nse, entry);
} else {
QTAILQ_INSERT_TAIL(&savevm_state.handlers, nse, entry);
}
+
+ if (savevm_state.handler_pri_head[priority] == NULL) {
+ savevm_state.handler_pri_head[priority] = nse;
+ }
}
static void savevm_state_handler_remove(SaveStateEntry *se)
{
+ SaveStateEntry *next;
+ MigrationPriority priority = save_state_priority(se);
+
+ if (se == savevm_state.handler_pri_head[priority]) {
+ next = QTAILQ_NEXT(se, entry);
+ if (next != NULL && save_state_priority(next) == priority) {
+ savevm_state.handler_pri_head[priority] = next;
+ } else {
+ savevm_state.handler_pri_head[priority] = NULL;
+ }
+ }
QTAILQ_REMOVE(&savevm_state.handlers, se, entry);
}
--
2.24.1
- [PULL 02/29] migration-test: Add migration multifd test, (continued)
- [PULL 02/29] migration-test: Add migration multifd test, Juan Quintela, 2020/01/20
- [PULL 04/29] migration-test: introduce functions to handle string parameters, Juan Quintela, 2020/01/20
- [PULL 03/29] migration: Make sure that we don't call write() in case of error, Juan Quintela, 2020/01/20
- [PULL 05/29] runstate: ignore finishmigrate -> prelaunch transition, Juan Quintela, 2020/01/20
- [PULL 06/29] ram.c: remove unneeded labels, Juan Quintela, 2020/01/20
- [PULL 07/29] migration: Rate limit inside host pages, Juan Quintela, 2020/01/20
- [PULL 08/29] migration: Fix incorrect integer->float conversion caught by clang, Juan Quintela, 2020/01/20
- [PULL 09/29] migration: Fix the re-run check of the migrate-incoming command, Juan Quintela, 2020/01/20
- [PULL 10/29] misc: use QEMU_IS_ALIGNED, Juan Quintela, 2020/01/20
- [PULL 11/29] migration: add savevm_state_handler_remove(), Juan Quintela, 2020/01/20
- [PULL 12/29] migration: savevm_state_handler_insert: constant-time element insertion,
Juan Quintela <=
- [PULL 13/29] migration/ram: Yield periodically to the main loop, Juan Quintela, 2020/01/20
- [PULL 14/29] migration/postcopy: reduce memset when it is zero page and matches_target_page_size, Juan Quintela, 2020/01/20
- [PULL 15/29] migration/postcopy: wait for decompress thread in precopy, Juan Quintela, 2020/01/20
- [PULL 16/29] migration/postcopy: count target page number to decide the place_needed, Juan Quintela, 2020/01/20
- [PULL 17/29] migration/postcopy: set all_zero to true on the first target page, Juan Quintela, 2020/01/20
- [PULL 18/29] migration/postcopy: enable random order target page arrival, Juan Quintela, 2020/01/20
- [PULL 19/29] migration/postcopy: enable compress during postcopy, Juan Quintela, 2020/01/20
- [PULL 20/29] migration/multifd: clean pages after filling packet, Juan Quintela, 2020/01/20
- [PULL 21/29] migration/multifd: not use multifd during postcopy, Juan Quintela, 2020/01/20
- [PULL 22/29] migration/multifd: fix nullptr access in terminating multifd threads, Juan Quintela, 2020/01/20