brintos

brintos / linux-shallow public Read only

0
0
Text · 3.3 KiB · 6820119 Raw
139 lines · c
1/*2 * Stress test for transparent huge pages, memory compaction and migration.3 *4 * Authors: Konstantin Khlebnikov <koct9i@gmail.com>5 *6 * This is free and unencumbered software released into the public domain.7 */8 9#include <stdlib.h>10#include <stdio.h>11#include <stdint.h>12#include <err.h>13#include <time.h>14#include <unistd.h>15#include <fcntl.h>16#include <string.h>17#include <sys/mman.h>18#include "vm_util.h"19#include "../kselftest.h"20 21int backing_fd = -1;22int mmap_flags = MAP_ANONYMOUS | MAP_NORESERVE | MAP_PRIVATE;23#define PROT_RW (PROT_READ | PROT_WRITE)24 25int main(int argc, char **argv)26{27	size_t ram, len;28	void *ptr, *p;29	struct timespec start, a, b;30	int i = 0;31	char *name = NULL;32	double s;33	uint8_t *map;34	size_t map_len;35	int pagemap_fd;36	int duration = 0;37 38	ksft_print_header();39 40	ram = sysconf(_SC_PHYS_PAGES);41	if (ram > SIZE_MAX / psize() / 4)42		ram = SIZE_MAX / 4;43	else44		ram *= psize();45	len = ram;46 47	while (++i < argc) {48		if (!strcmp(argv[i], "-h"))49			ksft_exit_fail_msg("usage: %s [-f <filename>] [-d <duration>] [size in MiB]\n",50					   argv[0]);51		else if (!strcmp(argv[i], "-f"))52			name = argv[++i];53		else if (!strcmp(argv[i], "-d"))54			duration = atoi(argv[++i]);55		else56			len = atoll(argv[i]) << 20;57	}58 59	ksft_set_plan(1);60 61	if (name) {62		backing_fd = open(name, O_RDWR);63		if (backing_fd == -1)64			ksft_exit_fail_msg("open %s\n", name);65		mmap_flags = MAP_SHARED;66	}67 68	warnx("allocate %zd transhuge pages, using %zd MiB virtual memory"69	      " and %zd MiB of ram", len >> HPAGE_SHIFT, len >> 20,70	      ram >> (20 + HPAGE_SHIFT - pshift() - 1));71 72	pagemap_fd = open("/proc/self/pagemap", O_RDONLY);73	if (pagemap_fd < 0)74		ksft_exit_fail_msg("open pagemap\n");75 76	len -= len % HPAGE_SIZE;77	ptr = mmap(NULL, len + HPAGE_SIZE, PROT_RW, mmap_flags, backing_fd, 0);78	if (ptr == MAP_FAILED)79		ksft_exit_fail_msg("initial mmap");80	ptr += HPAGE_SIZE - (uintptr_t)ptr % HPAGE_SIZE;81 82	if (madvise(ptr, len, MADV_HUGEPAGE))83		ksft_exit_fail_msg("MADV_HUGEPAGE");84 85	map_len = ram >> (HPAGE_SHIFT - 1);86	map = malloc(map_len);87	if (!map)88		ksft_exit_fail_msg("map malloc\n");89 90	clock_gettime(CLOCK_MONOTONIC, &start);91 92	while (1) {93		int nr_succeed = 0, nr_failed = 0, nr_pages = 0;94 95		memset(map, 0, map_len);96 97		clock_gettime(CLOCK_MONOTONIC, &a);98		for (p = ptr; p < ptr + len; p += HPAGE_SIZE) {99			int64_t pfn;100 101			pfn = allocate_transhuge(p, pagemap_fd);102 103			if (pfn < 0) {104				nr_failed++;105			} else {106				size_t idx = pfn >> (HPAGE_SHIFT - pshift());107 108				nr_succeed++;109				if (idx >= map_len) {110					map = realloc(map, idx + 1);111					if (!map)112						ksft_exit_fail_msg("map realloc\n");113					memset(map + map_len, 0, idx + 1 - map_len);114					map_len = idx + 1;115				}116				if (!map[idx])117					nr_pages++;118				map[idx] = 1;119			}120 121			/* split transhuge page, keep last page */122			if (madvise(p, HPAGE_SIZE - psize(), MADV_DONTNEED))123				ksft_exit_fail_msg("MADV_DONTNEED");124		}125		clock_gettime(CLOCK_MONOTONIC, &b);126		s = b.tv_sec - a.tv_sec + (b.tv_nsec - a.tv_nsec) / 1000000000.;127 128		ksft_print_msg("%.3f s/loop, %.3f ms/page, %10.3f MiB/s\t"129			       "%4d succeed, %4d failed, %4d different pages\n",130			       s, s * 1000 / (len >> HPAGE_SHIFT), len / s / (1 << 20),131			       nr_succeed, nr_failed, nr_pages);132 133		if (duration > 0 && b.tv_sec - start.tv_sec >= duration) {134			ksft_test_result_pass("Completed\n");135			ksft_finished();136		}137	}138}139