从Python和sh模块运行命令时,LXD容器上会发生数百万次关闭系统调用

从Python和sh模块运行命令时,LXD容器上会发生数百万次关闭系统调用,python,linux,containers,lxd,Python,Linux,Containers,Lxd,我有一个Python应用程序,其中多次使用Pythonsh模块来运行命令。另外,我使用LXD容器来运行独立测试 我注意到在LXD容器上运行测试时的性能非常不同,因此我开始降低Python脚本的复杂性 现在,scrip是一个简单的sh.nice(),但是主机和lxc容器之间有很大的区别 主人 容器 $ time python -c "import sh; sh.nice()" real 0m0.215s user 0m0.088s sys 0m0.120s 我的下一步是使用s

我有一个Python应用程序,其中多次使用Pythonsh模块来运行命令。另外,我使用LXD容器来运行独立测试

我注意到在LXD容器上运行测试时的性能非常不同,因此我开始降低Python脚本的复杂性

现在,scrip是一个简单的sh.nice(),但是主机和lxc容器之间有很大的区别

主人

容器

$ time python -c "import sh; sh.nice()"
real    0m0.215s
user    0m0.088s
sys     0m0.120s
我的下一步是使用strace,它说容器版本调用syscall
close
1048796次!!大多数情况下,它返回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并输出。有一条太大了。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

LXC、LXD和LXCFS的项目负责人回答了这个问题

这将迭代每个fd编号,直到RLIMIT_NOFILE,并逐个关闭它们,而不管fd是否确实存在

在正常系统上,这将被限制为1024,作为最大注释文件限制。在LXD容器中,我们将它提升到一个更高的值,导致花费的时间更长


因此,在lxd容器上使用模块可能更好。

LXC、lxd和LXCFS的项目负责人回答了这个问题

这将迭代每个fd编号,直到RLIMIT_NOFILE,并逐个关闭它们,而不管fd是否确实存在

在正常系统上,这将被限制为1024,作为最大注释文件限制。在LXD容器中,我们将它提升到一个更高的值,导致花费的时间更长


因此,最好在LXD容器上使用模块。

Python将尝试将所有FD从第三关闭到最大(通常是文件描述符的ULIMIT):考虑通过“代码> /ETC /安全/限制”来减少软限制。CONF(取决于DeXo)谢谢!原因就在这里。sh模块是关闭lxd容器中所有文件描述符的人,在lxd容器中,限制要高得多。我认为您应该从您打开的问题发布问题的解决方案,这样这个问题就不会没有答案。Python将尝试从第三个关闭所有FD,直到最大值(这通常是文件描述符的ulimit)考虑通过代码> > /ETC /安全/限制来减少软限制。CONF(取决于DISCO)谢谢!原因就在这里。sh模块是谁正在关闭lxd容器中的所有文件描述符,在lxd容器中,限制要高得多。我认为您应该发布您已打开的问题的解决方案,这样这个问题就不会没有答案。
$ 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