/* Global variable used to synchronize all of the vCPU threads. */ staticint iteration;
/* The cgroup memory controller root. Needed for lru_gen-based aging. */ char cgroup_root[PATH_MAX];
/* Defines what vCPU threads should do during a given iteration. */ staticenum { /* Run the vCPU to access all its memory. */
ITERATION_ACCESS_MEMORY, /* Mark the vCPU's memory idle in page_idle. */
ITERATION_MARK_IDLE,
} iteration_work;
/* The iteration that was last completed by each vCPU. */ staticint vcpu_last_completed_iteration[KVM_MAX_VCPUS];
/* Whether to overlap the regions of memory vCPUs access. */ staticbool overlap_memory_access;
int find_generation(struct memcg_stats *stats, long total_pages)
{ /* *Forfindingthegenerationthatcontainsourpages,usethesame *90%thresholdthatpage_idleuses.
*/ int gen = lru_gen_find_generation(stats, total_pages * 9 / 10);
if (gen >= 0) return gen;
if (!idle_pages_warn_only) {
TEST_FAIL("Could not find a generation with 90%% of guest memory (%ld pages).",
total_pages * 9 / 10); return gen;
}
/* *Wecouldn'tfindagenerationwith90%ofguestmemory,whichcan *happenifaccesstrackingisunreliable.Simplylookforamajority *ofpages.
*/
puts("WARNING: Couldn't find a generation with 90% of guest memory. " "Performance results may not be accurate.");
gen = lru_gen_find_generation(stats, total_pages / 2);
TEST_ASSERT(gen >= 0, "Could not find a generation with 50%% of guest memory (%ld pages).",
total_pages / 2); return gen;
}
/* Make a new generation */
clock_gettime(CLOCK_MONOTONIC, &ts_start);
lru_gen_do_aging(&stats, TEST_MEMCG_NAME);
ts_elapsed = timespec_elapsed(ts_start);
/* Check the generation again */
new_gen = find_generation(&stats, test_pages);
/* *Thisfunctionshouldonlybeinvokedwithnewly-accessedpages, *sopagesshouldalwaysmovetoanewergeneration.
*/ if (new_gen <= lru_gen_last_gen) { /* We did not move to a newer generation. */ long idle_pages = lru_gen_sum_memcg_stats_for_gen(lru_gen_last_gen,
&stats);
/* *Doapagetablescannow.Followinginitialpopulation,aging *maynotcausethepagestomovetoanewergeneration.Do *anagingpassnowsothatfutureagingpassesalwaysmove *pagestoanewergeneration.
*/
printf("Initial aging pass (lru_gen)\n");
lru_gen_do_aging(&stats, TEST_MEMCG_NAME);
TEST_ASSERT(lru_gen_sum_memcg_stats(&stats) >= test_pages, "Not all pages accounted for (looking for %ld). " "Was the memcg set up correctly?", test_pages);
access_memory(vm, nr_vcpus, ACCESS_WRITE, "Re-populating memory");
lru_gen_read_memcg_stats(&stats, TEST_MEMCG_NAME);
lru_gen_last_gen = find_generation(&stats, test_pages);
}
/* As a control, read and write to the populated memory first. */
access_memory(vm, nr_vcpus, ACCESS_WRITE, "Writing to populated memory");
access_memory(vm, nr_vcpus, ACCESS_READ, "Reading from populated memory");
/* Repeat on memory that has been marked as idle. */
mark_memory_idle(vm, nr_vcpus);
access_memory(vm, nr_vcpus, ACCESS_WRITE, "Writing to idle memory");
mark_memory_idle(vm, nr_vcpus);
access_memory(vm, nr_vcpus, ACCESS_READ, "Reading from idle memory");
staticvoid help(char *name)
{
puts("");
printf("usage: %s [-h] [-m mode] [-b vcpu_bytes] [-v vcpus] [-o] [-s mem_type]\n",
name);
puts("");
printf(" -h: Display this help message.");
guest_modes_help();
printf(" -b: specify the size of the memory region which should be\n" " dirtied by each vCPU. e.g. 10M or 3G.\n" " (default: 1G)\n");
printf(" -v: specify the number of vCPUs to run.\n");
printf(" -o: Overlap guest memory accesses instead of partitioning\n" " them into a separate region of memory for each vCPU.\n");
printf(" -w: Control whether the test warns or fails if more than 10%%\n" " of pages are still seen as idle/old after accessing guest\n" " memory. >0 == warn only, 0 == fail, <0 == auto. For auto\n" " mode, the test fails by default, but switches to warn only\n" " if NUMA balancing is enabled or the test detects it's running\n" " in a VM.\n");
backing_src_help("-s");
puts(""); exit(0);
}
if (idle_pages_warn_only == -1)
idle_pages_warn_only = access_tracking_unreliable();
if (lru_gen_usable()) { bool cg_created = true; int ret;
puts("Using lru_gen for aging");
use_lru_gen = true;
if (cg_find_controller_root(cgroup_root, sizeof(cgroup_root), "memory"))
ksft_exit_skip("Cannot find memory cgroup controller\n");
new_cg = cg_name(cgroup_root, TEST_MEMCG_NAME);
printf("Creating cgroup: %s\n", new_cg); if (cg_create(new_cg)) { if (errno == EEXIST) {
printf("Found existing cgroup");
cg_created = false;
} else {
ksft_exit_skip("could not create new cgroup: %s\n", new_cg);
}
}
/* *Thiswillforkoffanewprocesstorunthetestwithin *anewmemcg,soweneedtoproperlypropagatethereturn *valueup.
*/
ret = cg_run(new_cg, &run_test_for_each_guest_mode, ¶ms); if (cg_created)
cg_destroy(new_cg); if (ret < 0)
TEST_FAIL("child did not spawn or was abnormally killed"); if (ret) return ret;
} else {
page_idle_fd = __open_path_or_exit("/sys/kernel/mm/page_idle/bitmap", O_RDWR, "Is CONFIG_IDLE_PAGE_TRACKING enabled?");
close(page_idle_fd);
puts("Using page_idle for aging");
run_test_for_each_guest_mode(NULL, ¶ms);
}
return0;
}
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.15 Sekunden
(vorverarbeitet am 2026-10-11)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.