mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-23 17:33:23 +00:00
Add per-CPU counters and track RSS for each Vmar
This commit is contained in:
152
test/apps/mmap/mmap_vmrss.c
Normal file
152
test/apps/mmap/mmap_vmrss.c
Normal file
@ -0,0 +1,152 @@
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
#define _GNU_SOURCE
|
||||
|
||||
#include "../network/test.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/mman.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#define PAGE_SIZE 4096
|
||||
#define NUM_PAGES 1024
|
||||
#define TOTAL_SIZE (PAGE_SIZE * NUM_PAGES)
|
||||
|
||||
typedef enum rss_type {
|
||||
anon,
|
||||
file,
|
||||
total,
|
||||
} rss_type;
|
||||
|
||||
long get_vm_rss_kb(rss_type type)
|
||||
{
|
||||
pid_t pid = getpid();
|
||||
char path[64];
|
||||
snprintf(path, sizeof(path), "/proc/%d/status", pid);
|
||||
|
||||
FILE *f = fopen(path, "r");
|
||||
if (!f) {
|
||||
perror("fopen /proc/[pid]/status");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
char line[256];
|
||||
long rss_kb = -1;
|
||||
const char *target_field = NULL;
|
||||
switch (type) {
|
||||
case anon:
|
||||
target_field = "RssAnon:";
|
||||
break;
|
||||
case file:
|
||||
target_field = "RssFile:";
|
||||
break;
|
||||
case total:
|
||||
target_field = "VmRSS:";
|
||||
break;
|
||||
default:
|
||||
perror("Unknown rss_type\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
while (fgets(line, sizeof(line), f)) {
|
||||
if (strncmp(line, target_field, strlen(target_field)) == 0) {
|
||||
sscanf(line + strlen(target_field), "%ld", &rss_kb);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
|
||||
if (rss_kb < 0) {
|
||||
fprintf(stderr, "Failed to parse VmRSS\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return rss_kb;
|
||||
}
|
||||
|
||||
FN_TEST(rss_anon)
|
||||
{
|
||||
void *mem = mmap(NULL, TOTAL_SIZE, PROT_READ | PROT_WRITE,
|
||||
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
|
||||
if (mem == MAP_FAILED) {
|
||||
perror("mmap");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// The first call to `TEST_SUCC` and `get_vm_rss_kb()` may trigger
|
||||
// lazy mapping of additional pages, such as shared libraries or files.
|
||||
// These pages are not counted in RSS until they are actually accessed.
|
||||
TEST_SUCC(get_vm_rss_kb(anon));
|
||||
|
||||
long rss_anon_before = TEST_SUCC(get_vm_rss_kb(anon));
|
||||
long rss_file_before = TEST_SUCC(get_vm_rss_kb(file));
|
||||
long rss_before = TEST_SUCC(get_vm_rss_kb(total));
|
||||
|
||||
// Trigger page faults
|
||||
for (int i = 0; i < NUM_PAGES; ++i) {
|
||||
volatile char *p = (char *)mem + i * PAGE_SIZE;
|
||||
*p = 42;
|
||||
}
|
||||
|
||||
TEST_RES(get_vm_rss_kb(anon),
|
||||
_ret - rss_anon_before == NUM_PAGES * (PAGE_SIZE / 1024));
|
||||
TEST_RES(get_vm_rss_kb(file), _ret == rss_file_before);
|
||||
TEST_RES(get_vm_rss_kb(total),
|
||||
_ret - rss_before == NUM_PAGES * (PAGE_SIZE / 1024));
|
||||
|
||||
TEST_SUCC(munmap(mem, TOTAL_SIZE));
|
||||
|
||||
TEST_RES(get_vm_rss_kb(anon), _ret == rss_anon_before);
|
||||
TEST_RES(get_vm_rss_kb(file), _ret == rss_file_before);
|
||||
TEST_RES(get_vm_rss_kb(total), _ret == rss_before);
|
||||
}
|
||||
END_TEST()
|
||||
|
||||
FN_TEST(rss_file)
|
||||
{
|
||||
const char *filename = "rss_test_file";
|
||||
int fd = TEST_SUCC(open(filename, O_CREAT | O_RDWR, 0600));
|
||||
|
||||
TEST_SUCC(ftruncate(fd, TOTAL_SIZE));
|
||||
|
||||
// The first call to `TEST_SUCC` and `get_vm_rss_kb()` may trigger
|
||||
// lazy mapping of additional pages, such as shared libraries or files.
|
||||
// These pages are not counted in RSS until they are actually accessed.
|
||||
TEST_SUCC(get_vm_rss_kb(anon));
|
||||
|
||||
long rss_anon_before = TEST_SUCC(get_vm_rss_kb(anon));
|
||||
long rss_file_before = TEST_SUCC(get_vm_rss_kb(file));
|
||||
long rss_before = TEST_SUCC(get_vm_rss_kb(total));
|
||||
|
||||
void *mem = mmap(NULL, TOTAL_SIZE, PROT_READ, MAP_PRIVATE, fd, 0);
|
||||
if (mem == MAP_FAILED) {
|
||||
perror("mmap");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// Trigger page faults
|
||||
for (int i = 0; i < NUM_PAGES; ++i) {
|
||||
volatile char x = *((char *)mem + i * PAGE_SIZE);
|
||||
x++;
|
||||
}
|
||||
|
||||
TEST_RES(get_vm_rss_kb(file),
|
||||
_ret - rss_file_before == NUM_PAGES * (PAGE_SIZE / 1024));
|
||||
TEST_RES(get_vm_rss_kb(anon), _ret == rss_anon_before);
|
||||
TEST_RES(get_vm_rss_kb(total),
|
||||
_ret - rss_before == NUM_PAGES * (PAGE_SIZE / 1024));
|
||||
|
||||
TEST_SUCC(munmap(mem, TOTAL_SIZE));
|
||||
|
||||
TEST_RES(get_vm_rss_kb(anon), _ret == rss_anon_before);
|
||||
TEST_RES(get_vm_rss_kb(file), _ret == rss_file_before);
|
||||
TEST_RES(get_vm_rss_kb(total), _ret == rss_before);
|
||||
|
||||
close(fd);
|
||||
unlink(filename);
|
||||
}
|
||||
END_TEST()
|
@ -30,6 +30,7 @@ itimer/timer_create
|
||||
mmap/mmap_and_fork
|
||||
mmap/mmap_shared_filebacked
|
||||
mmap/mmap_readahead
|
||||
mmap/mmap_vmrss
|
||||
process/group_session
|
||||
process/job_control
|
||||
pthread/pthread_test
|
||||
@ -41,7 +42,7 @@ signal_c/signal_test
|
||||
"
|
||||
|
||||
for testcase in ${tests}
|
||||
do
|
||||
do
|
||||
echo "Running test ${testcase}......"
|
||||
${SCRIPT_DIR}/${testcase}
|
||||
done
|
||||
|
Reference in New Issue
Block a user