当我启动新进程时,NodeJS fork进程正在减慢所有其他分叉进程的速度

时间:2016-12-30 11:53:30

标签: node.js performance imagemagick multiprocessing fork

我有一个NodeJS程序,它使用ImageMagick从我的数据库中的某些文本创建图像。该程序使用

从我的NodeJs服务器中启动
import childProcess from 'child_process';
let args = [':imageId', '--max_old_space_size=4096'];
childProcess.fork('createImage.js', args);

创建图像的过程非常慢,在我的本地计算机上,对于尺寸为114x84cm的单张图像,可能需要5-6分钟。

我将尝试解释程序生命周期中发生的事情。

因此,当有人请求图片MyServer分叉新进程时,我有一个在进程MyServer上运行的服务器。

新进程ImageCreator1有一个来自promises的循环,并将一直等到所有问题都解决了。每个承诺使用ImageMagick

创建该大图像的一部分

在我的活动监视器中,我可以看到有一些正在运行的进程

Process Name   |  %CPU
MyServer       -  0.3
ImageCreator1  -  30.0
convert        -  0.1
convert        -  0.1
convert        -  0.2
convert        -  0.1

此外,我可以看到ImageCreator1运行异步4-5 ImageMagick转换进程以创建所有这些所需的小图片。

这一切都需要5分钟。创造大图像。

所以当我开始两个ImageCreators时,时间增加到9分钟。

Process Name   |  %CPU
MyServer       -  0.3
ImageCreator1  -  30.0
ImageCreator2  -  40.0
convert        -  0.1
convert        -  0.1
convert        -  0.2
convert        -  0.1
convert        -  0.1
convert        -  0.1
convert        -  0.2
convert        -  0.1

如果我开始ImageCreator3ImageCreator4变得越来越慢。我在想,当我开始一个新的过程,如果这个过程完成工作5分钟。然后,如果我同时开始五个过程,每个过程必须完成5分钟。但似乎随着每个新的ImageCreator,所有人的时间都会增加。

我仍然处于NodeJsOS这个问题的学习阶段,所以如果有人能解释会发生什么事情会很棒。

!!!更新IMAGECREATOR代码!!!

console.time('imageCreator');
process.title = 'imageCreator'+process.argv[2];

const fs = require('fs');
const gm = require('gm').subClass({imageMagick:true});
const Promise = require('bluebird');

var images = [], rows = [];
for(var i = 1; i<=100;i++){
    images.push(i);
}

for(var i = 1; i<=10;i++){

    rows.push(Promise.reduce(images, function(total, image){

        return new Promise(function(resolve, reject) {

            gm('xc:rgb('+(image*2)+','+image+','+(image*2)+')')
            .in('-units', 'PixelsPerInch')
            .in('-size', '100x100')
            .in('-density', 300)
            .in('-page', '+'+(image-100)*100+'+0')
            .toBuffer('miff', function(err, stream){
                    fs.appendFile(__dirname+'/test'+process.argv[2]+'.miff', stream, function(err){
                        if(err) reject(err);
                        else resolve(image);
                    });
            });

        });

    }));

}


Promise.all(rows).then(function( ) {
    console.timeEnd('imageCreator');
});

所以我正在做一些测试,以找出我的脚本的哪个部分存在问题。这是一个例子,当我在我的Mac上运行它时会发生什么。顺便说一下,我重新编译ImageMagick所以现在我有:

Version: ImageMagick 6.9.7-2 Q16 x86_64 2017-01-03 http://www.imagemagick.org
Copyright: © 1999-2017 ImageMagick Studio LLC
License: http://www.imagemagick.org/script/license.php
Features: Cipher DPC Modules 
Delegates (built-in): bzlib freetype jng jpeg ltdl lzma png tiff xml zlib

因此,当我在一个终端上运行上面的脚本时,我得到的时间如下:

Terminal1 - imageCreator: 7498.438ms - 7.4984380002sec.

但是当我同时尝试两个终端时:

Terminal1 - imageCreator: 14632.522ms - 14.632522sec.
Terminal2 - imageCreator: 13734ms - 13.734sec.

正如你所看到的,两者的时间几乎翻了一倍。

我的电脑有:

processor:2.7 GHz Intel Core i5
memory:8 GB 1867 MHz DDR3

所以发生了什么,我猜这里有ram,但是我对这种低级别的东西并不是很好,所以如果有人可以解释它会很棒。提前谢谢。

1 个答案:

答案 0 :(得分:1)

您执行此代码的计算机有多少CPU核心?当您使用child_process创建新流程时,您将开始新流程 - 这意味着操作系统调度程序将尝试与您的父流程并行运行新流程 - 但此要求多个CPU。

如果你没有多个CPU,那么OS调度程序将在运行你的主进程和你的子进程之间进行交换,并在同一个CPU上为每个CPU提供CPU时间,因此不会真正在&& 39; parallel&#39;中运行它们因为在任何给定时间只会执行一条指令。

另外需要注意的是ImageMagick:在多个进程中运行是否安全?

我对ImageMagick并不是很熟悉,但根据2009年的this old thread(现在可能会有所不同),ImageMagick使用自己的线程:因此不会在多个进程中同时运行它在任何加速。

希望有所帮助!