Skip to content

Commit 9e7cb94

Browse files
zhans00torvalds
authored andcommitted
selftests: vm: add KSM merging time test
Patch series "add KSM performance tests", v3. Extend KSM self tests with a performance benchmark. These tests are not part of regular regression testing, as they are mainly intended to be used by developers making changes to the memory management subsystem. This patch (of 2): Add ksm_merge_time() function to determine speed and time needed for merging. The total spent time is shown in seconds while speed is in MiB/s. User must specify the size of duplicated memory area (in MiB) before running the test. The test is run as follows: ./ksm_tests -P -s 100 The output: Total size: 100 MiB Total time: 0.201106786 s Average speed: 497.248 MiB/s Link: https://lkml.kernel.org/r/[email protected] Link: https://lkml.kernel.org/r/318b946ac80cc9205c89d0962048378f7ce0705b.1629386192.git.zhansayabagdaulet@gmail.com Signed-off-by: Zhansaya Bagdauletkyzy <[email protected]> Reviewed-by: Tyler Hicks <[email protected]> Reviewed-by: Pavel Tatashin <[email protected]> Signed-off-by: Andrew Morton <[email protected]> Signed-off-by: Linus Torvalds <[email protected]>
1 parent 584ff0d commit 9e7cb94

File tree

1 file changed

+70
-4
lines changed

1 file changed

+70
-4
lines changed

tools/testing/selftests/vm/ksm_tests.c

Lines changed: 70 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include <numa.h>
88

99
#include "../kselftest.h"
10+
#include "../../../../include/vdso/time64.h"
1011

1112
#define KSM_SYSFS_PATH "/sys/kernel/mm/ksm/"
1213
#define KSM_FP(s) (KSM_SYSFS_PATH s)
@@ -15,6 +16,7 @@
1516
#define KSM_PROT_STR_DEFAULT "rw"
1617
#define KSM_USE_ZERO_PAGES_DEFAULT false
1718
#define KSM_MERGE_ACROSS_NODES_DEFAULT true
19+
#define MB (1ul << 20)
1820

1921
struct ksm_sysfs {
2022
unsigned long max_page_sharing;
@@ -30,7 +32,8 @@ enum ksm_test_name {
3032
CHECK_KSM_MERGE,
3133
CHECK_KSM_UNMERGE,
3234
CHECK_KSM_ZERO_PAGE_MERGE,
33-
CHECK_KSM_NUMA_MERGE
35+
CHECK_KSM_NUMA_MERGE,
36+
KSM_MERGE_TIME
3437
};
3538

3639
static int ksm_write_sysfs(const char *file_path, unsigned long val)
@@ -86,13 +89,16 @@ static int str_to_prot(char *prot_str)
8689
static void print_help(void)
8790
{
8891
printf("usage: ksm_tests [-h] <test type> [-a prot] [-p page_count] [-l timeout]\n"
89-
"[-z use_zero_pages] [-m merge_across_nodes]\n");
92+
"[-z use_zero_pages] [-m merge_across_nodes] [-s size]\n");
9093

9194
printf("Supported <test type>:\n"
9295
" -M (page merging)\n"
9396
" -Z (zero pages merging)\n"
9497
" -N (merging of pages in different NUMA nodes)\n"
95-
" -U (page unmerging)\n\n");
98+
" -U (page unmerging)\n"
99+
" -P evaluate merging time and speed.\n"
100+
" For this test, the size of duplicated memory area (in MiB)\n"
101+
" must be provided using -s option\n\n");
96102

97103
printf(" -a: specify the access protections of pages.\n"
98104
" <prot> must be of the form [rwx].\n"
@@ -105,6 +111,7 @@ static void print_help(void)
105111
" Default: %d\n", KSM_USE_ZERO_PAGES_DEFAULT);
106112
printf(" -m: change merge_across_nodes tunable\n"
107113
" Default: %d\n", KSM_MERGE_ACROSS_NODES_DEFAULT);
114+
printf(" -s: the size of duplicated memory area (in MiB)\n");
108115

109116
exit(0);
110117
}
@@ -407,6 +414,47 @@ static int check_ksm_numa_merge(int mapping, int prot, int timeout, bool merge_a
407414
return KSFT_FAIL;
408415
}
409416

417+
static int ksm_merge_time(int mapping, int prot, int timeout, size_t map_size)
418+
{
419+
void *map_ptr;
420+
struct timespec start_time, end_time;
421+
unsigned long scan_time_ns;
422+
423+
map_size *= MB;
424+
425+
map_ptr = allocate_memory(NULL, prot, mapping, '*', map_size);
426+
if (!map_ptr)
427+
return KSFT_FAIL;
428+
429+
if (clock_gettime(CLOCK_MONOTONIC_RAW, &start_time)) {
430+
perror("clock_gettime");
431+
goto err_out;
432+
}
433+
if (ksm_merge_pages(map_ptr, map_size, start_time, timeout))
434+
goto err_out;
435+
if (clock_gettime(CLOCK_MONOTONIC_RAW, &end_time)) {
436+
perror("clock_gettime");
437+
goto err_out;
438+
}
439+
440+
scan_time_ns = (end_time.tv_sec - start_time.tv_sec) * NSEC_PER_SEC +
441+
(end_time.tv_nsec - start_time.tv_nsec);
442+
443+
printf("Total size: %lu MiB\n", map_size / MB);
444+
printf("Total time: %ld.%09ld s\n", scan_time_ns / NSEC_PER_SEC,
445+
scan_time_ns % NSEC_PER_SEC);
446+
printf("Average speed: %.3f MiB/s\n", (map_size / MB) /
447+
((double)scan_time_ns / NSEC_PER_SEC));
448+
449+
munmap(map_ptr, map_size);
450+
return KSFT_PASS;
451+
452+
err_out:
453+
printf("Not OK\n");
454+
munmap(map_ptr, map_size);
455+
return KSFT_FAIL;
456+
}
457+
410458
int main(int argc, char *argv[])
411459
{
412460
int ret, opt;
@@ -418,8 +466,9 @@ int main(int argc, char *argv[])
418466
int test_name = CHECK_KSM_MERGE;
419467
bool use_zero_pages = KSM_USE_ZERO_PAGES_DEFAULT;
420468
bool merge_across_nodes = KSM_MERGE_ACROSS_NODES_DEFAULT;
469+
long size_MB = 0;
421470

422-
while ((opt = getopt(argc, argv, "ha:p:l:z:m:MUZN")) != -1) {
471+
while ((opt = getopt(argc, argv, "ha:p:l:z:m:s:MUZNP")) != -1) {
423472
switch (opt) {
424473
case 'a':
425474
prot = str_to_prot(optarg);
@@ -453,6 +502,12 @@ int main(int argc, char *argv[])
453502
else
454503
merge_across_nodes = 1;
455504
break;
505+
case 's':
506+
size_MB = atoi(optarg);
507+
if (size_MB <= 0) {
508+
printf("Size must be greater than 0\n");
509+
return KSFT_FAIL;
510+
}
456511
case 'M':
457512
break;
458513
case 'U':
@@ -464,6 +519,9 @@ int main(int argc, char *argv[])
464519
case 'N':
465520
test_name = CHECK_KSM_NUMA_MERGE;
466521
break;
522+
case 'P':
523+
test_name = KSM_MERGE_TIME;
524+
break;
467525
default:
468526
return KSFT_FAIL;
469527
}
@@ -505,6 +563,14 @@ int main(int argc, char *argv[])
505563
ret = check_ksm_numa_merge(MAP_PRIVATE | MAP_ANONYMOUS, prot, ksm_scan_limit_sec,
506564
merge_across_nodes, page_size);
507565
break;
566+
case KSM_MERGE_TIME:
567+
if (size_MB == 0) {
568+
printf("Option '-s' is required.\n");
569+
return KSFT_FAIL;
570+
}
571+
ret = ksm_merge_time(MAP_PRIVATE | MAP_ANONYMOUS, prot, ksm_scan_limit_sec,
572+
size_MB);
573+
break;
508574
}
509575

510576
if (ksm_restore(&ksm_sysfs_old)) {

0 commit comments

Comments
 (0)