Newman.run вызывает увеличение heapused, но не освобождает память при повторении в итерациях

У меня очень небольшая коллекция с одним вызовом несуществующего URL-адреса, что приводит к ошибке.

Я повторяю это в циклах выдержки, каждый цикл генерирует всплеск памяти примерно на 2,9–3 МБ и не освобождает его. После первого запуска heapUsed составляет 8,8 МБ, а после десятого - 20,45 МБ.

Каждый рабочий цикл запускается с предварительно созданными параметрами, как показано ниже:

{
  "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, но это не сильно помогло.

Это проблема с функцией запуска модуля Ньюмана (вызывающая утечки памяти), иначе как я могу это исправить.

Версия Ньюмана - 3.8.3 для ОС Win 7.

3
0
421
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Это достигается за счет использования модуля child_process, который позволяет создать новый дочерний процесс для модуля, содержащего newman run code.

newmanCodeModule.js: (содержит специальный код Newman)

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

Главный модуль процесса

Вызов модуля Newman Run

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();
}

Другие вопросы по теме