clone()/ fork()/进程创建在某些机器上很慢

时间:2011-03-22 06:57:00

标签: linux performance ubuntu kernel

在我的某些机器上创建新进程非常慢,而不是其他机器。

这些机器都很相似,有些慢速机器在同一硬件和内核(2.6.32-26,Ubuntu 10.04)上运行与一些快速机器完全相同的工作负载。不涉及创建流程的任务在所有计算机上都具有相同的速度。

例如,该程序在受影响的计算机上执行速度慢约50倍:

int main()
{
    int i;
    for (i=0;i<10000;i++)
    {
        int p = fork();
        if (!p) exit(0);
        waitpid(p);
    }
    return 0;
}

什么可能导致任务创建速度慢得多,以及我可以在机器中寻找其他差异?

Edit1:运行bash脚本(因为它们产生了很多子进程)在这些机器上运行速度也非常慢,并且对慢速脚本的分析显示clone()内核调用的速度减慢。

Edit2:vmstat在快速与慢速机器上没有显示任何显着差异。他们都有足够的RAM用于他们的工作负载,而不是交换。

编辑3:我在dmesg

中看不到任何可疑的内容

Edit4:我现在不确定为什么这是在stackoverflow上,我不是在问上面的示例程序(只是用它来演示问题),而是Linux管理/调优,但如果人们认为它属于这里,很酷。

5 个答案:

答案 0 :(得分:2)

我们的应用程序堆栈遇到了同样的问题,注意到应用程序性能的大幅下降和使用strace的更长克隆时间。在18个节点上使用您的测试程序,我在同样的3上重现了您的结果,我们遇到了缓慢的克隆时间。所有节点都以相同的方式配置,但硬件略有不同。我们检查了BIOS,vmstat,vm.overcommit_memory并更换了RAM而没有任何改进。然后,我们将驱动器移至更新的硬件,问题得到解决。

CentOS 5.9 2.6.18-348.1.1.el5#1 SMP Tue Jan 22 16:19:19 EST 2013 x86_64 x86_64 x86_64 GNU / Linux

“坏”和“好”lspci:

$ diff ../bad_lspci_sort ../good_lspci_sort 
< Ethernet controller: Intel Corporation 82579LM Gigabit Network Connection (rev 05)
> Ethernet controller: Intel Corporation 82574L Gigabit Network Connection

< Host bridge: Intel Corporation Xeon E3-1200 Processor Family DRAM Controller (rev 09)
> Host bridge: Intel Corporation Xeon E3-1200 v2/Ivy Bridge DRAM Controller (rev 09)

< ISA bridge: Intel Corporation C204 Chipset Family LPC Controller (rev 05)
> ISA bridge: Intel Corporation C202 Chipset Family LPC Controller (rev 05)

< PCI bridge: Intel Corporation 6 Series/C200 Series Chipset Family PCI Express Root Port 6 (rev b5)
> PCI bridge: Intel Corporation 6 Series/C200 Series Chipset Family PCI Express Root Port 7 (rev b5)

< VGA compatible controller: Matrox Electronics Systems Ltd. MGA G200e [Pilot] ServerEngines (SEP1) (rev 04)
> VGA compatible controller: Matrox Electronics Systems Ltd. MGA G200eW WPCM450 (rev 0a)

答案 1 :(得分:1)

我可能首先使用strace来查看正在运行的系统调用,以及缓慢挂起的系统调用。 我也很好奇你在这里如何使用waitpid()。在我的系统上,waitpid的签名是

pid_t waitpid(pid_t pid, int *status, int options);

看起来你正在使用wait(),但传递子进程的pid而不是int“status”,它具有你要测试的状态标志的OR。如果PID最终被解释为状态掩码,这可能会导致一些奇怪的事情发生。

答案 2 :(得分:0)

要看的差异是内核(参数,设备驱动程序,活动模块)和硬件(cpu版本,cpu数量,内存配置,外围设备)。

另外:机器在重启/重启后会改变行为吗?

编辑:

低性能可能与(虚拟)内存层次结构有关。这种层次结构非常复杂,这种复杂性会导致奇怪的效果。在从TLB到数据缓存到主存储器的路上,可能会发生奇怪的冲突。这些可能是由于不同机器内核的内存布局略有不同,或者因为内存层次结构(硬件)实际上略有不同。

当然可能有其他原因,奇怪的外围设备(产生中断),不同的工作负载(例如活动进程的数量),......

如果您可以解决此问题,请分享结果!感谢。

答案 3 :(得分:0)

所有系统的/sbin/sysctl vm.overcommit_memory值是否相同?如果没有,那可以解释其中的差异。

允许过度使用会使fork()更快,但这意味着新分配的页面将不会被RAM或交换支持。如果/当您触摸未支持的页面时,操作系统必须找到它的支持 - 如果不能,则该进程被杀死。如果所有孩子都exec(),这不是问题,就像在system()调用中所发生的那样,因为所有这些未支持的页面都被丢弃了;但是,它可能会导致fork()的其他用户出现严重问题。

答案 4 :(得分:0)

您是否检查了BIOS配置,以防您禁用CPU缓存,或者电源配置搞砸了,或者某些系统过热,或者某些内存被低频...