diff --git a/.eslintrc b/.eslintrc index 6bbf0e8..5fbca9e 100644 --- a/.eslintrc +++ b/.eslintrc @@ -25,7 +25,7 @@ "no-implied-eval": 2, "no-labels": 2, "no-with": 2, - "no-loop-func": 1, + "no-loop-func": 0, "no-native-reassign": 2, "no-redeclare": [2, {"builtinGlobals": true}], "no-delete-var": 2, diff --git a/README.md b/README.md index b471e6f..1ebe3a3 100644 --- a/README.md +++ b/README.md @@ -79,7 +79,7 @@ require('xprofiler')(); * **patch_http**: 是否对原生 http 模块进行 patch,输出 http 请求相关信息,默认 `true` * **patch_http_timeout**: 默认 http 请求超时时间,单位秒,作为 http 请求统计,默认 `30` * **check_throw**: `xprofiler` 启动时检测错误时是否需要 throw,默认 `true` -* **auto_incr_heap_limit_size**: `enable_auto_incr_heap_limit` 开启后,每次自动增加的堆上限大小,默认为 `512` (MB) +* **auto_incr_heap_limit_size**: `enable_auto_incr_heap_limit` 开启后,每次自动增加的堆上限大小,默认为 `256` (MB) * **enable_log_uv_handles**: 是否要采集 libuv 句柄的详细分类信息,比如 tcp 句柄数量,timers 数量,文件句柄数量等,默认为 `true` * **enable_fatal_error_hook**: 是否需要在 V8 出现 FatalError 时配置钩子,默认 `true` * **enable_fatal_error_report**: 是否需要在 V8 出现 FataLError 时导出 Report 文件,默认 `true` diff --git a/test/fixtures/cases/limit.js b/test/fixtures/cases/limit.js new file mode 100644 index 0000000..193df3d --- /dev/null +++ b/test/fixtures/cases/limit.js @@ -0,0 +1,18 @@ +'use strict'; + +const path = require('path'); +const { filterTestCaseByPlatform } = require('../utils'); + +const exitFatalErrorScriptPath = path.join(__dirname, '../scripts/fatal_error.js'); + +exports = module.exports = function () { + const list = [ + { + title: 'limit hook is valid', + subTitle: 'auto increase heap limit is ok.', + jspath: exitFatalErrorScriptPath, + } + ]; + + return filterTestCaseByPlatform(list); +}; \ No newline at end of file diff --git a/test/fixtures/scripts/fatal_error.js b/test/fixtures/scripts/fatal_error.js index d01b762..189a181 100644 --- a/test/fixtures/scripts/fatal_error.js +++ b/test/fixtures/scripts/fatal_error.js @@ -16,6 +16,6 @@ process.send({ type: utils.clientConst.xprofilerDone }); const array = []; setInterval(() => { - array.push(new Array(10e6).fill('*')); - console.log('now rss:', process.memoryUsage().rss / 1024 / 1024 + ' Mb'); + array.push(new Array(0.5 * 10e6).fill('*')); + console.log('now rss:', process.memoryUsage().rss / 1024 / 1024 + ' MB'); }, Number(process.env.XPROFILER_FATAL_ERROR_INTERVAL) || 1); \ No newline at end of file diff --git a/test/limit.test.js b/test/limit.test.js new file mode 100644 index 0000000..71a75dc --- /dev/null +++ b/test/limit.test.js @@ -0,0 +1,70 @@ +'use strict'; + +const os = require('os'); +const fs = require('fs'); +const cp = require('child_process'); +const path = require('path'); +const expect = require('expect.js'); +const promisify = require('util').promisify; +const readdir = promisify(fs.readdir); +const unlink = promisify(fs.unlink); +const utils = require('./fixtures/utils'); +const cases = require('./fixtures/cases/limit')(); + +const currentPlatform = os.platform(); + +const logdir = utils.createLogDir('logdir_limit'); + +const casesLength = cases.length; + +for (const cse of cases) { + const ospt = cse.platform || currentPlatform; + describe(`[${ospt}] ${cse.title}`, function () { + const initialHeapLimit = 128; + const autoIncreaseHeapLimitSize = 128; + const MB = 1024 * 1024; + + let stdout = ''; + let subprocess = null; + before(async function () { + subprocess = cp.fork(cse.jspath, { + execArgv: [`--max-old-space-size=${initialHeapLimit}`], + env: Object.assign({}, process.env, { + XPROFILER_LOG_DIR: logdir, + XPROFILER_LOG_LEVEL: 2, + XPROFILER_LOG_TYPE: 1, + XPROFILER_ENABLE_AUTO_INCR_HEAP_LIMIT: 'YES', + XPROFILER_AUTO_INCR_HEAP_LIMIT_SIZE: autoIncreaseHeapLimitSize, + XPROFILER_FATAL_ERROR_INTERVAL: 500, + }, cse.env), + stdio: [0, 'pipe', 'pipe', 'ipc'], + }); + subprocess.stdout.on('data', chunk => stdout += chunk.toString()); + await utils.sleep(5000); + subprocess.kill(); + console.log('========= stdout =========\n\n', stdout, '\n========= end ========='); + }); + after(async function () { + const files = await readdir(logdir); + for (const file of files) { + await unlink(path.join(logdir, file)); + } + if (cse === cases[casesLength - 1]) { + utils.cleanDir(logdir); + } + + subprocess.kill(); + }); + + for (let i = 1; i < 3; i++) { + it(`${cse.subTitle} with ${i} times heap increase factor`, function () { + const increaseLog = `current_heap_limit is ${(initialHeapLimit + (i - 1) * autoIncreaseHeapLimitSize) * MB}, ` + + `initial_heap_limit is ${initialHeapLimit * MB}, ` + + `auto_incr_heap_limit_size is ${autoIncreaseHeapLimitSize}, ` + + `increased_heap is ${initialHeapLimit * MB + i * autoIncreaseHeapLimitSize * MB}`; + console.log('increaseLog:', increaseLog); + expect(stdout).to.contain(increaseLog); + }); + } + }); +} \ No newline at end of file