在微不足道的“sleep 1”的情况下,是什么导致了 QEMU 的开销?
What causes overhead in QEMU in case of trivial `sleep 1`?
实验:
我 运行 sleep 1
在 strace -tt
下(报告所有系统调用的时间戳)在主机和 QEMU 来宾中,并注意到达到某个系统调用所需的时间(clock_nanosleep
) 在客人的情况下 几乎大两倍:
- 1.813 毫秒 在主机上 vs
- 3.396 毫秒 在来宾中。
这里是full host strace -tt sleep 1 and here is full QEMU strace -tt sleep 1.
以下是您已经可以看出差异的摘录:
主持人:
Time diff timestamp (as reported by strace)
0.000 / 0.653 ms: 13:13:56.452820 execve("/usr/bin/sleep", ["sleep", "1"], 0x7ffded01ecb0 /* 53 vars */) = 0
0.653 / 0.023 ms: 13:13:56.453473 brk(NULL) = 0x5617efdea000
0.676 / 0.063 ms: 13:13:56.453496 arch_prctl(0x3001 /* ARCH_??? */, 0x7fffeb7041b0) = -1 EINVAL (Invalid argument)
QEMU:
Time diff timestamp (as reported by strace)
0.000 / 1.008 ms: 12:12:03.164063 execve("/usr/bin/sleep", ["sleep", "1"], 0x7ffd0bd93e50 /* 13 vars */) = 0
1.008 / 0.119 ms: 12:12:03.165071 brk(NULL) = 0x55b78c484000
1.127 / 0.102 ms: 12:12:03.165190 arch_prctl(0x3001 /* ARCH_??? */, 0x7ffcb5dfd850) = -1 EINVAL (Invalid argument)
问题:
- 是什么导致了减速和开销?它不使用任何硬件(如 GPU、磁盘等),因此没有 t运行slation 层。我还多次尝试 运行 命令以确保可以缓存的所有内容都缓存在客户机中。
- 有没有办法加快速度?
更新:
cpupower frequency-set --governor performance
时间是:
- 主机:0.922ms
- 访客:1.412ms
- 图片在
/dev/shm
(-drive file=/dev/shm/root
):
- 主机:0.922ms
- 访客:1.280 毫秒
PS
我修改了 strace 的“裸”输出,以便它包括 (1) 从 0 开始的第一个系统调用的时间,然后是 (2) 系统调用的持续时间,以便于理解。为了完整起见,脚本是 here.
我是这样启动qemu的:
qemu-system-x86_64 -enable-kvm -cpu host -smp 4 -m 4G -nodefaults -no-user-config -nographic -no-reboot \
-kernel $HOME/devel/vmlinuz-5.13.0-20-generic \
-append 'earlyprintk=hvc0 console=hvc0 root=/dev/sda rw' \
-drive file=$HOME/devel/images/root,if=ide,index=0,media=disk,format=raw \
-device virtio-serial,id=virtio-serial0 -chardev stdio,mux=on,id=host-io,signal=off -device virtconsole,chardev=host-io,id=console0
这是预料之中的,考虑到 strace
的实现方式,即通过 ptrace(2)
系统调用:每次被跟踪进程执行系统调用或获取信号时,进程都会被强制 stopped 并将控制权传递给跟踪过程,在 strace
的情况下,它会 同步 执行所有解包和打印,即同时保持跟踪的进程停止了。这种路径会以指数方式增加任何仿真开销。
strace strace
本身是有指导意义的——你会看到它不会让被跟踪的进程继续(使用 ptrace(PTRACE_SYSCALL, ...)
),直到它处理并写出与当前相关的所有内容系统调用。
请注意,为了 运行 一个“琐碎的” sleep 1
命令,动态链接器甚至在到达 sleep
的入口点之前将执行几十个系统调用二进制。
我认为优化 strace
不值得花时间;如果您打算 运行 strace 作为审计工具而不是调试工具(通过 运行 在 strace
或类似的生产任务下执行),您应该重新考虑您的设计 ;-)
原来我的(定制内核)缺少 CONFIG_HYPERVISOR_GUEST=y
选项(和几个嵌套选项)。
实验:
我 运行 sleep 1
在 strace -tt
下(报告所有系统调用的时间戳)在主机和 QEMU 来宾中,并注意到达到某个系统调用所需的时间(clock_nanosleep
) 在客人的情况下 几乎大两倍:
- 1.813 毫秒 在主机上 vs
- 3.396 毫秒 在来宾中。
这里是full host strace -tt sleep 1 and here is full QEMU strace -tt sleep 1.
以下是您已经可以看出差异的摘录:
主持人:
Time diff timestamp (as reported by strace)
0.000 / 0.653 ms: 13:13:56.452820 execve("/usr/bin/sleep", ["sleep", "1"], 0x7ffded01ecb0 /* 53 vars */) = 0
0.653 / 0.023 ms: 13:13:56.453473 brk(NULL) = 0x5617efdea000
0.676 / 0.063 ms: 13:13:56.453496 arch_prctl(0x3001 /* ARCH_??? */, 0x7fffeb7041b0) = -1 EINVAL (Invalid argument)
QEMU:
Time diff timestamp (as reported by strace)
0.000 / 1.008 ms: 12:12:03.164063 execve("/usr/bin/sleep", ["sleep", "1"], 0x7ffd0bd93e50 /* 13 vars */) = 0
1.008 / 0.119 ms: 12:12:03.165071 brk(NULL) = 0x55b78c484000
1.127 / 0.102 ms: 12:12:03.165190 arch_prctl(0x3001 /* ARCH_??? */, 0x7ffcb5dfd850) = -1 EINVAL (Invalid argument)
问题:
- 是什么导致了减速和开销?它不使用任何硬件(如 GPU、磁盘等),因此没有 t运行slation 层。我还多次尝试 运行 命令以确保可以缓存的所有内容都缓存在客户机中。
- 有没有办法加快速度?
更新:
cpupower frequency-set --governor performance
时间是:- 主机:0.922ms
- 访客:1.412ms
- 图片在
/dev/shm
(-drive file=/dev/shm/root
):- 主机:0.922ms
- 访客:1.280 毫秒
PS
我修改了 strace 的“裸”输出,以便它包括 (1) 从 0 开始的第一个系统调用的时间,然后是 (2) 系统调用的持续时间,以便于理解。为了完整起见,脚本是 here.
我是这样启动qemu的:
qemu-system-x86_64 -enable-kvm -cpu host -smp 4 -m 4G -nodefaults -no-user-config -nographic -no-reboot \
-kernel $HOME/devel/vmlinuz-5.13.0-20-generic \
-append 'earlyprintk=hvc0 console=hvc0 root=/dev/sda rw' \
-drive file=$HOME/devel/images/root,if=ide,index=0,media=disk,format=raw \
-device virtio-serial,id=virtio-serial0 -chardev stdio,mux=on,id=host-io,signal=off -device virtconsole,chardev=host-io,id=console0
这是预料之中的,考虑到 strace
的实现方式,即通过 ptrace(2)
系统调用:每次被跟踪进程执行系统调用或获取信号时,进程都会被强制 stopped 并将控制权传递给跟踪过程,在 strace
的情况下,它会 同步 执行所有解包和打印,即同时保持跟踪的进程停止了。这种路径会以指数方式增加任何仿真开销。
strace strace
本身是有指导意义的——你会看到它不会让被跟踪的进程继续(使用 ptrace(PTRACE_SYSCALL, ...)
),直到它处理并写出与当前相关的所有内容系统调用。
请注意,为了 运行 一个“琐碎的” sleep 1
命令,动态链接器甚至在到达 sleep
的入口点之前将执行几十个系统调用二进制。
我认为优化 strace
不值得花时间;如果您打算 运行 strace 作为审计工具而不是调试工具(通过 运行 在 strace
或类似的生产任务下执行),您应该重新考虑您的设计 ;-)
原来我的(定制内核)缺少 CONFIG_HYPERVISOR_GUEST=y
选项(和几个嵌套选项)。