1

我有一个 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,它表示容器版本调用系统调用close1,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
4

1 回答 1

0

LXC、LXD、LXCFS项目负责人在此回答问题

这会遍历每个 fd 编号直到 RLIMIT_NOFILE,一个一个地关闭它们,而不管 fd 是否确实存在。

在正常系统上,这将被限制在 1024 作为最多评论 NOFILE 限制。在 LXD 容器中,我们将它提高到了更高的值,导致它需要更长的时间。

所以也许最好在 lxd 容器上使用 subprocess 模块

于 2017-10-02T08:50:27.910 回答