Skip to the content.

yyds-fs DAMON 局部性实验

这个实验在 host 上用 DAMON 观察 collei 虚拟机 yyds-fs

本实验真正有意义的模式是 --guest-ram。它会解析 QEMU 进程的 /proc/<pid>/maps,找到 /memfd:memory-backend-memfd,然后用 DAMON fvaddr 只监控这一段映射。

当前 yyds-fs 的 guest RAM 映射为:

0x00007faeabfff000-0x00007fb0abfff000 8.000 GiB /memfd:memory-backend-memfd

这段地址是 QEMU 中承载 guest RAM 的 HVA。观察它可以回答:guest 内部的 GVA 访问经过 GVA->GPA,再表现为 QEMU RAMBlock/HVA offset 之后,原本的局部性还剩多少。

构建

cd /home/martins3/data/vn/docs/kernel/mm/damon
gcc -O2 -Wall -Wextra -o damon_locality.out damon_locality.c
gcc -O2 -Wall -Wextra -o damon_guest_load.out damon_guest_load.c
gcc -O2 -Wall -Wextra -o redis_resp_load.out redis_resp_load.c
ssh martins3@10.0.70.0 'cd /home/martins3/data/vn/docs/kernel/mm/damon && gcc -O2 -Wall -Wextra -o damon_guest_load.guest.out damon_guest_load.c'
ssh -p 51404 martins3@localhost 'cd /home/martins3/data/vn/docs/kernel/mm/damon && gcc -O2 -Wall -Wextra -o redis_resp_load.guest.out redis_resp_load.c'

命令

空闲基线:

sudo ./damon_locality.out --vm yyds-fs --duration 10 --snapshot-ms 1000 --top 5
sudo ./damon_locality.out --vm yyds-fs --guest-ram --duration 10 --snapshot-ms 1000 --min-regions 100 --max-regions 1000 --top 8

顺序访问 hotset:

ssh martins3@10.0.70.0 'cd /home/martins3/data/vn/docs/kernel/mm/damon && nohup ./damon_guest_load.guest.out --mode seq-hotset --total-mb 2048 --hot-mb 256 --seconds 20 > /tmp/damon_seq_hotset.log 2>&1 &'
sudo ./damon_locality.out --vm yyds-fs --guest-ram --duration 12 --snapshot-ms 1000 --min-regions 100 --max-regions 1000 --top 8

随机访问 256 MiB hotset:

ssh martins3@10.0.70.0 'cd /home/martins3/data/vn/docs/kernel/mm/damon && nohup ./damon_guest_load.guest.out --mode random-hotset --total-mb 2048 --hot-mb 256 --seconds 20 > /tmp/damon_random_hotset.log 2>&1 &'
sudo ./damon_locality.out --vm yyds-fs --guest-ram --duration 12 --snapshot-ms 1000 --min-regions 100 --max-regions 1000 --top 8

随机访问完整 2 GiB 区间:

ssh martins3@10.0.70.0 'cd /home/martins3/data/vn/docs/kernel/mm/damon && nohup ./damon_guest_load.guest.out --mode random-full --total-mb 2048 --seconds 20 > /tmp/damon_random_full.log 2>&1 &'
sudo ./damon_locality.out --vm yyds-fs --guest-ram --duration 12 --snapshot-ms 1000 --min-regions 100 --max-regions 1000 --top 8

host 物理机本地 workload 对照:

./damon_guest_load.out --mode seq-hotset --total-mb 2048 --hot-mb 256 --seconds 25 &
load_pid=$!
sudo ./damon_locality.out --pid "$load_pid" --duration 8 --snapshot-ms 1000 --min-regions 100 --max-regions 1000 --top 8
wait "$load_pid"

./damon_guest_load.out --mode random-hotset --total-mb 2048 --hot-mb 256 --seconds 25 &
load_pid=$!
sudo ./damon_locality.out --pid "$load_pid" --duration 8 --snapshot-ms 1000 --min-regions 100 --max-regions 1000 --top 8
wait "$load_pid"

./damon_guest_load.out --mode random-full --total-mb 2048 --seconds 25 &
load_pid=$!
sudo ./damon_locality.out --pid "$load_pid" --duration 8 --snapshot-ms 1000 --min-regions 100 --max-regions 1000 --top 8
wait "$load_pid"

Redis/Docker 对照实验:

# host Redis
docker run -d --name damon-redis-host --network host redis:7-alpine \
  redis-server --port 6380 --save "" --appendonly no --protected-mode no

# guest Redis
ssh -p 51404 martins3@localhost \
  'echo a | sudo -S docker run -d --name damon-redis-guest --network host redis:7-alpine \
  redis-server --port 6380 --save "" --appendonly no --protected-mode no'

# 准备相同数据集:262144 个 key,每个 value 4096 字节,约 1 GiB value payload。
./redis_resp_load.out --port 6380 --mode prepare \
  --total-keys 262144 --hot-keys 65536 --value-bytes 4096 --pipeline 128

ssh -p 51404 martins3@localhost \
  'cd /home/martins3/data/vn/docs/kernel/mm/damon && ./redis_resp_load.guest.out --port 6380 --mode prepare \
  --total-keys 262144 --hot-keys 65536 --value-bytes 4096 --pipeline 128'

host Redis GET hotset,DAMON 观察容器内 redis-server 的 host PID:

redis_pid=$(docker inspect -f '' damon-redis-host)
./redis_resp_load.out --port 6380 --mode get-hotset \
  --total-keys 262144 --hot-keys 65536 --value-bytes 4096 --pipeline 128 --seconds 45 &
load_pid=$!
echo a | sudo -S ./damon_locality.out --pid "$redis_pid" \
  --duration 15 --snapshot-ms 1000 --min-regions 100 --max-regions 1000 --top 8
wait "$load_pid"

guest Redis GET hotset,host DAMON 观察 QEMU guest RAM memfd:

ssh -p 51404 martins3@localhost \
  'cd /home/martins3/data/vn/docs/kernel/mm/damon && ./redis_resp_load.guest.out --port 6380 --mode get-hotset \
  --total-keys 262144 --hot-keys 65536 --value-bytes 4096 --pipeline 128 --seconds 45' &
load_pid=$!
echo a | sudo -S ./damon_locality.out --vm yyds-fs --guest-ram \
  --duration 15 --snapshot-ms 1000 --min-regions 100 --max-regions 1000 --top 8
wait "$load_pid"

set-hotset 可以替换 get-hotset,它会随机覆盖同一个 hotset,比 GET 更偏向写数据页。 但 Redis 的访问路径仍然会受到协议解析、client buffer、dict/robj 元数据和 jemalloc 复用影响。

观测结果

过滤后的空闲基线:

2 GiB 分配中顺序访问 256 MiB hotset:

2 GiB 分配中随机访问 256 MiB hotset:

随机访问完整 2 GiB 分配:

host 物理机本地 workload:

Redis/Docker workload:

结论

yyds-fs 来说,用 DAMON fvaddr 过滤到 QEMU guest RAM 后可以看到:局部性不会因为 GVA->GPA->HVA 转换就完全消失。

所以当前实验的回答是:

hotset 的大小大体能保留下来,但细粒度连续性和局部性会被 guest 分配、guest 页表映射和背景 guest 活动削弱。

如果目标是用 Redis 继续验证这个结论,需要更谨慎地解释:

本站所有文章转发 CSDN 将按侵权追究法律责任,其它情况随意。