node.js - Newman.run 导致 heapUsed 增加但在迭代中重复时不会释放内存

标签 node.js postman postman-collection-runner

我有一个非常小的集合,只调用了一个不存在的 url,从而产生错误。

我在浸泡周期中对其进行迭代,每个周期都会产生大约 2.9-3 MB 的内存峰值并且不会释放它。 第一次运行后 heapUsed 为 8.8 MB,第十次运行后达到 20.45 MB。

每个运行周期都使用预先生成的选项集运行,如下所示:

{
  "collection": "c:/workspace/postman/common/iterationExample.postman_collection",
  "environment": {
    "id": "3afdcf58-7ddd-71eb-ef87-c75501df3267",
    "name": "SchemaValidations",
    "values": [
      {
        "enabled": true,
        "key": "some server",
        "value": "some url",
        "type": "text"
      },
      {
        "enabled": true,
        "key": "ip",
        "value": "xx.xx.xx.xx",
        "type": "text"
      },
      {
        "enabled": true,
        "key": "another server",
        "value": "another url",
        "type": "text"
      }
    ],
    "timestamp": 1517304219458,
    "_postman_variable_scope": "environment",
    "_postman_exported_at": "2018-01-30T09:23:48.085Z",
    "_postman_exported_using": "Postman/5.5.2"
  },
  "globals": {
    "name": "globals-env",
    "values": [],
    "_postman_variable_scope": "globals"
  },
  "delayRequest": 500,
  "timeoutRequest": 180000,
  "insecure": true,
  "bail": false,
  "suppressExitCode": true,
  "reporters": [
    "cli"
  ],
  "reporter": {
    "cli": {}
  },
  "folder": "some collection folder"
}

我已经实现了一个小的 heapUse 跟踪器以及 Newman 运行代码,如下所示:

var prevStats;
var memPth;
var markHeap, markHeapInit;
function logMemory (path,comment,mark) {
    if (! fs.existsSync(path)) {
        fs.mkdirSync(path, DIR_MODE);
    }
    memPth = path;
    path = pathUtils.posix.join(path,"memoryLeak.txt");
    if (comment) comment = comment.replace(/(.+)/,' - $1');
    var memStats = process.memoryUsage();
    fs.appendFileSync(path,`\r\n\r\n***Memory Log ${comment}\r\n`);
    var diff;
    if (prevStats) {
        _.forEach (
            ["heapUsed"],
            key => {
                if (memStats.hasOwnProperty(key)) {
                    diff = memStats[key]-prevStats[key];
                    fs.appendFileSync(path,`\r\nSpike in ${key}: ${diff}`);
                    if (diff < 0) {
                        fs.appendFileSync(path,`   $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$`);
                    } else if (diff > 500000) {
                        fs.appendFileSync(path,`   ######################################`);
                    }
                    fs.appendFileSync(path,`\r\nHeapUsed: ${memStats[key]}`);
                }
            }
        );
    }
    if (mark) {
        fs.appendFileSync(path,`\r\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%`);
        if (markHeap) {
            fs.appendFileSync(path,`\r\n\r\n***Marked Spike ${comment} - ${memStats.heapUsed - markHeap} - total: ${memStats.heapUsed}\r\n`);
        }
        markHeap = memStats.heapUsed;
        if (!markHeapInit) {
            markHeapInit = markHeap;
        } else {
            fs.appendFileSync(path,`\r\n***Total Spike ${comment} - ${memStats.heapUsed - markHeapInit} - total: ${memStats.heapUsed}\r\n`);
        }
        fs.appendFileSync(path,`\r\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%`);
    }
    prevStats = memStats;
}


function requireNewman() {
    //Clearing the require.cache before calling require('newman') gets us a new instance
    for (var property in require.cache) {
        if (Object.prototype.hasOwnProperty.call(require.cache,property) && property.indexOf('/node_modules/newman') !== -1) {
            delete require.cache[property];
        }
    }
    return require('newman');
}

var Newman = requireNewman();

//Neman run code
Newman.run(opts, function (err, summary) {
        logMemory(memPth,'After Newman.run');
        // done with newman task
        runNewmanCb(null, {err: err, summary: summary});

    }).on('beforeIteration', function (err, args) {
        if (!err && args.cursor.cycles > 1) {
            console.log(`Iteration ${args.cursor.iteration}/${args.cursor.cycles}`);
        }
        logMemory(memPth,'beforeIteration Event');
    }).on('exception', function (err, args) {
        if (args.error.name !== 'ReferenceError') {
            // unknown exception let's log it
        }
        logMemory(memPth,'exception Event');
    }).on('beforeItem', function (err, args) {
        logMemory(memPth,'beforeItem Event');
    }).on('request', function (err, args) {
        var size = args.response && args.response.size();
        size = size && (size.header || 0) + (size.body || 0) || 0;

        if (err) {
            console.error('%s %s [errored]', args.request.method, args.request.url);

        } else {


            var reqHeaders = _.reduce(args.request.headers.members, function (headerObj, val) {
                headerObj[`${val.key}`] = val.value;
                return headerObj;
            },{});

            var requestBodyStr = '';
            var bodyLogStr = 'body';
            switch (args.request.body.mode) {
                case 'raw':
                    if (args.request.body.raw) {
                        try {
                            // try to parse it so it can be displayed beautified by the logger
                            requestBodyStr = JSON.parse(args.request.body.raw);
                        } catch (e) {
                            requestBodyStr = args.request.body.raw;
                        }
                    }
                    break;
                case 'formdata':
                case 'urlencoded':
                case 'binary':
                case 'file':
                    bodyLogStr = args.request.body.mode;
                    requestBodyStr = args.request.body[args.request.body.mode];
                    break;
                default:
                    requestBodyStr = args.request.body;
            }


            var respHeaders = _.reduce(args.response.headers.members, function (headerObj, val) {
                headerObj[`${val.key}`] = val.value;
                return headerObj;
            },{});

            var respStream = _.get(args, 'response.stream', '');
            var respBodyStr = Buffer.from(respStream).toString();
            var jsonRE = /json/i;
            if ((respHeaders['Content-Type'] && jsonRE.test(respHeaders['Content-Type']))
            ||  (reqHeaders['Content-Type'] && jsonRE.test(reqHeaders['Content-Type']))) {
                try {
                    respBodyStr = JSON.parse(respBodyStr);
                } catch (e) {
                    console.log('Unable to parse JSON response', e);
                }
            }

            if (typeof respBodyStr != 'object') {
                // likely a string so lets make sure the body gets logged on a newline
                respBodyStr = `\n${respBodyStr}`;
            }

        }

    }).on('assertion', function (err, args) {
        var passed = !err;

        // print each test assertions
    }).on('script', function (err, args) {
        if (err) {
        }
        logMemory(memPth,'script Event');
    }).on('item', function (err, args) {
        logMemory(memPth,'item Event');
    }).on('console', function (err, args) {
        var lvl = 'info';
        switch (args.level) {
            case 'log':
                lvl = 'info';
                break;
            default:
                lvl = args.level;
        }
        logMemory(memPth,'console Event');
    });
}

十个运行周期的内存峰值跟踪为:

***Memory Log  - Before Newman require


***Memory Log  - After Newman require

Spike in heapUsed: 41450104   ######################################
HeapUsed: 70518752

***Memory Log  - beforeIteration Event

Spike in heapUsed: 12883520   ######################################
HeapUsed: 83402272

***Memory Log  - beforeItem Event

Spike in heapUsed: 262592
HeapUsed: 83664864

***Memory Log  - script Event

Spike in heapUsed: 1299272   ######################################
HeapUsed: 84964136

***Memory Log  - request Event

Spike in heapUsed: 1255296   ######################################
HeapUsed: 86219432

***Memory Log  - script Event

Spike in heapUsed: -1266024   $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
HeapUsed: 84953408

***Memory Log  - assertion Event

Spike in heapUsed: 110152
HeapUsed: 85063560

***Memory Log  - item Event

Spike in heapUsed: 113432
HeapUsed: 85176992

***Memory Log  - After Newman.run

Spike in heapUsed: 1070224   ######################################
HeapUsed: 86247216

***Memory Log  - Before Newman require

Spike in heapUsed: 5754872   ######################################
HeapUsed: 92002088

***Memory Log  - After Newman require

Spike in heapUsed: 138624
HeapUsed: 92140712

***Memory Log  - beforeIteration Event

Spike in heapUsed: 14925168   ######################################
HeapUsed: 107065880

***Memory Log  - beforeItem Event

Spike in heapUsed: 114584
HeapUsed: 107180464

***Memory Log  - script Event

Spike in heapUsed: 1051224   ######################################
HeapUsed: 108231688

***Memory Log  - request Event

Spike in heapUsed: 521584   ######################################
HeapUsed: 108753272

***Memory Log  - script Event

Spike in heapUsed: 818384   ######################################
HeapUsed: 109571656

***Memory Log  - assertion Event

Spike in heapUsed: 116792
HeapUsed: 109688448

***Memory Log  - item Event

Spike in heapUsed: 126640
HeapUsed: 109815088

***Memory Log  - After Newman.run

Spike in heapUsed: 778640   ######################################
HeapUsed: 110593728

***Memory Log  - Before Newman require

Spike in heapUsed: 5657224   ######################################
HeapUsed: 116250952

***Memory Log  - After Newman require

Spike in heapUsed: 108216
HeapUsed: 116359168

***Memory Log  - beforeIteration Event

Spike in heapUsed: 10163576   ######################################
HeapUsed: 126522744

***Memory Log  - beforeItem Event

Spike in heapUsed: 111504
HeapUsed: 126634248

***Memory Log  - script Event

Spike in heapUsed: 1147912   ######################################
HeapUsed: 127782160

***Memory Log  - request Event

Spike in heapUsed: 492672
HeapUsed: 128274832

***Memory Log  - script Event

Spike in heapUsed: 874616   ######################################
HeapUsed: 129149448

***Memory Log  - assertion Event

Spike in heapUsed: 107632
HeapUsed: 129257080

***Memory Log  - item Event

Spike in heapUsed: 110608
HeapUsed: 129367688

***Memory Log  - After Newman.run

Spike in heapUsed: 716344   ######################################
HeapUsed: 130084032

***Memory Log  - Before Newman require

Spike in heapUsed: -452992   $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
HeapUsed: 129631040

***Memory Log  - After Newman require

Spike in heapUsed: 101280
HeapUsed: 129732320

***Memory Log  - beforeIteration Event

Spike in heapUsed: 10040104   ######################################
HeapUsed: 139772424

***Memory Log  - beforeItem Event

Spike in heapUsed: 105448
HeapUsed: 139877872

***Memory Log  - script Event

Spike in heapUsed: 1048712   ######################################
HeapUsed: 140926584

***Memory Log  - request Event

Spike in heapUsed: 504352   ######################################
HeapUsed: 141430936

***Memory Log  - script Event

Spike in heapUsed: 786344   ######################################
HeapUsed: 142217280

***Memory Log  - assertion Event

Spike in heapUsed: 135240
HeapUsed: 142352520

***Memory Log  - item Event

Spike in heapUsed: 98360
HeapUsed: 142450880

***Memory Log  - After Newman.run

Spike in heapUsed: 813816   ######################################
HeapUsed: 143264696

***Memory Log  - Before Newman require

Spike in heapUsed: -8588720   $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
HeapUsed: 134675976

***Memory Log  - After Newman require

Spike in heapUsed: 106616
HeapUsed: 134782592

***Memory Log  - beforeIteration Event

Spike in heapUsed: 9580888   ######################################
HeapUsed: 144363480

***Memory Log  - beforeItem Event

Spike in heapUsed: 110704
HeapUsed: 144474184

***Memory Log  - script Event

Spike in heapUsed: 1029288   ######################################
HeapUsed: 145503472

***Memory Log  - request Event

Spike in heapUsed: 469720
HeapUsed: 145973192

***Memory Log  - script Event

Spike in heapUsed: 820608   ######################################
HeapUsed: 146793800

***Memory Log  - assertion Event

Spike in heapUsed: 119352
HeapUsed: 146913152

***Memory Log  - item Event

Spike in heapUsed: 103312
HeapUsed: 147016464

***Memory Log  - After Newman.run

Spike in heapUsed: 861520   ######################################
HeapUsed: 147877984

***Memory Log  - Before Newman require

Spike in heapUsed: -3996896   $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
HeapUsed: 143881088

***Memory Log  - After Newman require

Spike in heapUsed: 103552
HeapUsed: 143984640

***Memory Log  - beforeIteration Event

Spike in heapUsed: 5518896   ######################################
HeapUsed: 149503536

***Memory Log  - beforeItem Event

Spike in heapUsed: 129160
HeapUsed: 149632696

***Memory Log  - script Event

Spike in heapUsed: 1055240   ######################################
HeapUsed: 150687936

***Memory Log  - request Event

Spike in heapUsed: 524808   ######################################
HeapUsed: 151212744

***Memory Log  - script Event

Spike in heapUsed: 830496   ######################################
HeapUsed: 152043240

***Memory Log  - assertion Event

Spike in heapUsed: 124872
HeapUsed: 152168112

***Memory Log  - item Event

Spike in heapUsed: 102320
HeapUsed: 152270432

***Memory Log  - After Newman.run

Spike in heapUsed: 705120   ######################################
HeapUsed: 152975552

***Memory Log  - Before Newman require

Spike in heapUsed: -5252008   $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
HeapUsed: 147723544

***Memory Log  - After Newman require

Spike in heapUsed: 97632
HeapUsed: 147821176

***Memory Log  - beforeIteration Event

Spike in heapUsed: 563360   ######################################
HeapUsed: 148384536

***Memory Log  - beforeItem Event

Spike in heapUsed: 118816
HeapUsed: 148503352

***Memory Log  - script Event

Spike in heapUsed: 1044776   ######################################
HeapUsed: 149548128

***Memory Log  - request Event

Spike in heapUsed: 537360   ######################################
HeapUsed: 150085488

***Memory Log  - script Event

Spike in heapUsed: 884552   ######################################
HeapUsed: 150970040

***Memory Log  - assertion Event

Spike in heapUsed: 111296
HeapUsed: 151081336

***Memory Log  - item Event

Spike in heapUsed: 101712
HeapUsed: 151183048

***Memory Log  - After Newman.run

Spike in heapUsed: 684200   ######################################
HeapUsed: 151867248

***Memory Log  - Before Newman require

Spike in heapUsed: 5902880   ######################################
HeapUsed: 157770128

***Memory Log  - After Newman require

Spike in heapUsed: 106848
HeapUsed: 157876976

***Memory Log  - beforeIteration Event

Spike in heapUsed: 10480696   ######################################
HeapUsed: 168357672

***Memory Log  - beforeItem Event

Spike in heapUsed: 112040
HeapUsed: 168469712

***Memory Log  - script Event

Spike in heapUsed: 1059784   ######################################
HeapUsed: 169529496

***Memory Log  - request Event

Spike in heapUsed: 474552
HeapUsed: 170004048

***Memory Log  - script Event

Spike in heapUsed: 780448   ######################################
HeapUsed: 170784496

***Memory Log  - assertion Event

Spike in heapUsed: 99568
HeapUsed: 170884064

***Memory Log  - item Event

Spike in heapUsed: 109568
HeapUsed: 170993632

***Memory Log  - After Newman.run

Spike in heapUsed: 687376   ######################################
HeapUsed: 171681008

***Memory Log  - Before Newman require

Spike in heapUsed: -16935080   $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
HeapUsed: 154745928

***Memory Log  - After Newman require

Spike in heapUsed: 107600
HeapUsed: 154853528

***Memory Log  - beforeIteration Event

Spike in heapUsed: 9497672   ######################################
HeapUsed: 164351200

***Memory Log  - beforeItem Event

Spike in heapUsed: 108360
HeapUsed: 164459560

***Memory Log  - script Event

Spike in heapUsed: 1048400   ######################################
HeapUsed: 165507960

***Memory Log  - request Event

Spike in heapUsed: 539696   ######################################
HeapUsed: 166047656

***Memory Log  - script Event

Spike in heapUsed: 803928   ######################################
HeapUsed: 166851584

***Memory Log  - assertion Event

Spike in heapUsed: 101560
HeapUsed: 166953144

***Memory Log  - item Event

Spike in heapUsed: 101512
HeapUsed: 167054656

***Memory Log  - After Newman.run

Spike in heapUsed: 658168   ######################################
HeapUsed: 167712824

***Memory Log  - Before Newman require

Spike in heapUsed: -3456624   $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
HeapUsed: 164256200

***Memory Log  - After Newman require

Spike in heapUsed: 108560
HeapUsed: 164364760

***Memory Log  - beforeIteration Event

Spike in heapUsed: -4130248   $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
HeapUsed: 160234512

***Memory Log  - beforeItem Event

Spike in heapUsed: 119920
HeapUsed: 160354432

***Memory Log  - script Event

Spike in heapUsed: 1055864   ######################################
HeapUsed: 161410296

***Memory Log  - request Event

Spike in heapUsed: 511176   ######################################
HeapUsed: 161921472

***Memory Log  - script Event

Spike in heapUsed: 782560   ######################################
HeapUsed: 162704032

***Memory Log  - assertion Event

Spike in heapUsed: 101496
HeapUsed: 162805528

***Memory Log  - item Event

Spike in heapUsed: 101512
HeapUsed: 162907040

***Memory Log  - After Newman.run

Spike in heapUsed: 735088   ######################################
HeapUsed: 163642128

我还实现了一个递归事件发射器 gc util,但它没有太大帮助。

这是 Newman 模块运行函数的问题(导致内存泄漏),否则我该如何解决。

Win 7 操作系统上的 Newman 版本为 3.8.3。

最佳答案

这是通过使用 child_process 模块实现的,该模块允许为包含 newman run code 的模块创建一个新的子进程

newmanCodeModule.js:(包含 newman 特定代码)

Newman.run(opts, function (err, summary) { ...

进程主模块

Newman 运行模块调用

var processMaster = require('child_process');
//args contain the newman option inputs
processMaster.execSync (`npm run newmanCodeModule.js ${args}`);

内存清理调用(垃圾收集 Linux 和 Win 平台上分配的堆 - Linux 尚未测试)

var curHeapUsed;

function killChildRuns (cb) {
    var curProcPid = process.pid,
        stdout;
    var processMaster = require('child_process');
    if (/^win/.test(process.platform)) {
        stdout = processMaster.execSync('WMIC process where name="node.exe" get ProcessId, CommandLine');
        stdout = typeof stdout === 'object' ? stdout.toString() : stdout;
        _.forEach (
            stdout.split(/[\n\r]+/),
            pinfo => {
                var match = pinfo.match(/\s+(\d+)\s*$/);
                if (match) {
                    var thisPid = match[1];
                    if (parseInt(thisPid) !== curProcPid && !pinfo.match(/webServices/i)) {
                        processMaster.execSync (`taskkill /PID ${thisPid}`);
                    }
                }
            }
        );
    } else {
        stdout = processMaster.execSync("ps -eo pid,lstart,cmd | grep node");
        stdout = typeof stdout === 'object' ? stdout.toString() : stdout;
        _.forEach (
            stdout.split(/[\n\r]+/),
            pinfo => {
                var thisPid = pinfo.match(/([^\s]+\s+){6}/).match(/^([^\s]+)\s+(.+)[^\s]+\s*$/)[0];
                if (pinfo.match(/\s+\d+\s*$/) && !(thisPid === curProcPid || pinfo.match(/webServices/i))) {
                    processMaster.execute (`"kill -9" ${thisPid}`);
                }
            }
        );
    }
    processMaster = null;
    var newHeapUsed = process.memoryUsage().heapUsed;
    if (curHeapUsed) {
        var heapDiff = newHeapUsed  - curHeapUsed;
        console.log("Memory Spike after Running iteration suite:");
        console.log("*********************************************");
        console.log('HeapDiff = '+parseFloat(heapDiff / (1024 * 1024))+ ' MB');
        console.log("*********************************************");
    } else {
        curHeapUsed = newHeapUsed;
    }
    if (cb) cb();
}

关于node.js - Newman.run 导致 heapUsed 增加但在迭代中重复时不会释放内存,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49773766/

相关文章:

javascript - REST API azure 语音转文本(已识别 : Text=undefined)

javascript - 如何通过 Node 中的关键字获取对象值

json - 使用 Postman 编码变量

Postman Newman - 在 Postman 中工作的请求在 Newman 中失败并带有 ETIMEDOUT

javascript - 即使事件循环已被占用,如何始终以超时终止 NodeJs 脚本?

javascript - 在 express 中捕获来自 mongoose 查询的错误

json - Postman中Elasticsearch的不正确curl语法

java - 即使正确的JSON JAVA Volley,凭证响应也无效

cookies - Postman App 不添加 cookie 请求