我有一个Python应用程序,我多次使用Python sh 模块来运行命令。另外,我使用 LXD 容器来运行独立测试。
我注意到在LXD容器上运行我的测试的性能非常不同,所以我开始降低Python脚本的复杂性。
现在,脚本是一个简单的 sh.nice(),但主机和lxc容器之间存在很大差异。
主机
$ time python -c "import sh; sh.nice()"
real 0m0.077s
user 0m0.052s
sys 0m0.012s
容器
$ time python -c "import sh; sh.nice()"
real 0m0.215s
user 0m0.088s
sys 0m0.120s
我的下一步是使用strace,它表示容器版本调用系统调用close
1,048,796次!大多数时候它返回EBADF(错误的文件描述符)。
这就是我所做的;发生了什么?
$ uname -a
Linux cmp-1 4.4.0-96-generic #119-Ubuntu SMP Tue Sep 12 14:59:54 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux
$ lxc launch ubuntu:precise new-precise-sh
$ lxc exec new-precise-sh -- bash
$ apt-get install python-pip
$ pip install sh
$ strace -f -e close python -c "import sh; sh.nice()" 2>&1 | wc -l
1048796
在不同文件中运行带有输出的strace。有一个太大 strace.2618
$ strace -ff -o strace python -c "import sh; sh.nice()"
$ ls -la
total 75276
drwxrwxr-x 2 user user 4096 Sep 27 16:58 .
drwxr-xr-x 41 user user 4096 Sep 27 16:45 ..
-rw-r--r-- 1 root root 121780 Sep 27 16:33 strace.2615
-rw-r--r-- 1 root root 3995 Sep 27 16:33 strace.2616
-rw-r--r-- 1 root root 6108 Sep 27 16:33 strace.2617
-rw-r--r-- 1 root root 76558803 Sep 27 16:33 strace.2618
-rw-r--r-- 1 root root 362363 Sep 27 16:33 strace.2619
-rw-r--r-- 1 root root 10748 Sep 27 16:33 strace.2620
文件内容如下:
$ cat strace.2618
...................
...................
getrlimit(RLIMIT_NOFILE, {rlim_cur=1024*1024, rlim_max=1024*1024}) = 0
close(3) = 0
close(4) = 0
close(5) = -1 EBADF (Bad file descriptor)
close(6) = -1 EBADF (Bad file descriptor)
close(7) = 0
close(8) = 0
close(9) = -1 EBADF (Bad file descriptor)
close(10) = 0
close(11) = -1 EBADF (Bad file descriptor)
...................
...................
close(33) = -1 EBADF (Bad file descriptor)
close(34) = -1 EBADF (Bad file descriptor)
close(35) = -1 EBADF (Bad file descriptor)
close(36) = -1 EBADF (Bad file descriptor)
close(37) = -1 EBADF (Bad file descriptor)
close(38) = -1 EBADF (Bad file descriptor)
...................
...................
close(1048568) = -1 EBADF (Bad file descriptor)
close(1048569) = -1 EBADF (Bad file descriptor)
close(1048570) = -1 EBADF (Bad file descriptor)
close(1048571) = -1 EBADF (Bad file descriptor)
close(1048572) = -1 EBADF (Bad file descriptor)
close(1048573) = -1 EBADF (Bad file descriptor)
close(1048574) = -1 EBADF (Bad file descriptor)
close(1048575) = -1 EBADF (Bad file descriptor)
ioctl(1, SNDCTL_TMR_TIMEBASE or TCGETS, {B38400 -opost -isig -icanon -echo ...}) = 0
答案 0 :(得分:0)
LXC,LXD和LXCFS的项目负责人回答了问题here。
这会迭代每个单独的fd编号,直到RLIMIT_NOFILE,逐个关闭它们,无论fd是否确实存在。
在普通系统上,最高评论NOFILE限制为1024。在LXD容器中,我们将其提升到更高的值,导致它需要更长的时间。
所以也许最好在lxd容器上使用subprocess模块。