我想限制 DPDK 应用程序的 CPU 使用率以进行测试。经过一番快速搜索,我发现控制组 (cgroups) 可能适合我的需求。所以我首先安装了cgroup-bin
。
sudo apt-get install cgroup-bin
然后我通过在 下创建一个目录来创建子系统/sys/fs/cgroup/cpu
。
mkdir -v /sys/fs/cgroup/cpu/dpdk
然后我将对 CPU 使用率的限制写入cpu.cfs_period_us
和cpu.cfs_quota_us
。例如,我想将我的 DPDK 应用程序的 CPU 使用率限制为 30%。
cd /sys/fs/cgroup/cpu/dpdk
echo 1000000 > cpu.cfs_period_us
echo 300000 > cpu.cfs_quota_us
此方法在运行仅使用一个核心的 DPDK 应用程序时有效。例如,examples/skeleton
cd /home/wang/dpdk-17.02/examples/skeleton
make
./build/basicfwd -c 1 -n 2
pgrep basicfwd > /sys/fs/cgroup/cpu/dpdk/tasks
我可以看到top
basicfwd 的 CPU 使用率实际上为 30%。
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
3346 root 20 0 4222472 3100 2780 R 30.0 0.0 0:56.35 basicfwd
但是当我运行使用多个核心的 DPDK 应用程序时,结果有点奇怪。例如,我想在 运行 L3 forward 示例应用程序examples/l3fwd
。
cd /home/wang/dpdk-17.02/examples/l3fwd
make
./build/l3fwd -l 1,2 -n 2 -- -p 0x3 -P --config="(0,0,1),(1,0,2)" --parse-ptype
pgrep l3fwd > /sys/fs/cgroup/cpu/dpdk/tasks
当我打开时top
,我看到的 CPU 使用率l3fwd
是 130%,而不是我预期的 30%。
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
3404 root 20 0 4305752 5092 2728 R 130.3 0.0 0:25.98 l3fwd
看起来限制只适用于一个核心。然而这一页它表示配额和期限参数以 CPU 为基础运行
cpu.cfs_quota_us
指定 cgroup 中所有任务在一个周期(由 cpu.cfs_period_us 定义)内可以运行的总时间(以微秒 (µs,此处表示为“us”))。一旦 cgroup 中的任务用完了配额指定的所有时间,它们就会在周期指定的剩余时间内受到限制,并且不允许运行,直到下一个周期。如果 cgroup 中的任务应该能够每 1 秒访问单个 CPU 0.2 秒,请将 cpu.cfs_quota_us 设置为 200000,将 cpu.cfs_period_us 设置为 1000000。请注意,配额和周期参数以 CPU 为基础运行。例如,要允许进程充分利用两个 CPU,请将 cpu.cfs_quota_us 设置为 200000,将 cpu.cfs_period_us 设置为 100000。
我这里遗漏了什么?我应该怎么做才能将多核 DPDK 应用程序的 CPU 使用率限制在 100% 以下?
答案1
总结:
- 使用
for i in $(pgrep -w l3fwd); do echo $i > tasks; done
细节:
我认为在您的情况下,pgrep 的任务分配需要一些改进才能处理报告的多个 ID。
如果它返回一个 PID,那么一切正常,但如果返回更多 PID,cgroup 接口实际上会报告
pgrep: write error: Invalid argument
也许您只是简化了您的报告,但请仔细检查所有任务是否都在 cgroups 任务文件中并使用循环(或任何其他解决方法)。
$ stress-ng -c 4
$ for i in $(pgrep stress); do echo $i > /sys/fs/cgroup/cpu/dpdk/tasks; done
$ cat tasks
28543
28544
[...]
现在,对于您的具体情况,l3fwd 有一个进程但有三个线程。因此,pgrep
只会报告主 pid,其他(主循环)不受限制。您可以在构建和测试它时通过ps axlf
vsps -eLf
和pgrep
输出看到。
. /usr/share/dpdk/dpdk-sdk-env.sh
mkdir -p l3fwd
make -C /usr/share/dpdk/examples/l3fwd "O=$(pwd)/l3fwd/"
# config /etc/dpdk/dpdk.conf and /etc/dpdk/interfaces
service dpdk restart
$(pwd)/l3fwd/l3fwd -l 1,2 --socket-mem 512 -- -p 0x3 -P --config="(0,0,1),(1,0,2)" --parse-ptype
因此,您必须将pgrep -w
其与上述内容结合起来。
for i in $(pgrep -w l3fwd); do echo $i > tasks; done
瞧,来自:
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
29849 root 20 0 703052 4184 3336 R 200,7 0,0 0:17.36 l3fwd
到
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
29849 root 20 0 703052 4184 3336 R 29,8 0,0 0:34.11 l3fwd
仍然请参阅我最初的评论,除了实验之外,请不要限制 DPDK CPU 消耗 - 然后不要使用 DPDK。