UNPKG

@phenixrts/aerospike

Version:
328 lines (276 loc) 7.25 kB
// ***************************************************************************** // Copyright 2013-2017 Aerospike, Inc. // // Licensed under the Apache License, Version 2.0 (the "License") // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // ***************************************************************************** var Table = require('cli-table') var yargs = require('yargs') var MEM_MATCH = /(\d+(\.\d+)?) MB/ var TABLE_CHARS = { top: '', 'top-mid': '', 'top-left': '', 'top-right': '', bottom: '', 'bottom-mid': '', 'bottom-left': '', 'bottom-right': '', left: '', 'left-mid': '', mid: '', 'mid-mid': '', right: '', 'right-mid': '', middle: '' } var TABLE_STYLE = { 'padding-left': 4, 'padding-right': 0, head: ['blue'], border: ['grey'], compact: true } var ITERATION_COUNT = 0 var memCnt = 0 var memMin var memMax var memRanges = [] // ***************************************************************************** // Options Parsing // ***************************************************************************** var argp = yargs .usage('$0 [options]') .options({ help: { boolean: true, describe: 'Display this message.' }, factor: { alias: 'f', default: 1, describe: 'Factor to filter by.' }, start: { alias: 's', default: undefined, describe: 'Start GC range.' }, end: { alias: 'e', default: undefined, describe: 'End GC range.' } }) var argv = argp.argv if (argv.help === true) { argp.showHelp() process.exit() } // ***************************************************************************** // Functions // ***************************************************************************** var MEM_MAX_MB = 100 var MEM_BUCKETS = 100 function memoryBar (minUsedMb, maxUsedMb) { var minUsedLen = Math.floor(minUsedMb / MEM_MAX_MB * MEM_BUCKETS) var minUsedBar = Buffer.alloc(minUsedLen) if (minUsedLen > 0) { minUsedBar.fill(']') } var maxUsedLen = Math.floor(maxUsedMb / MEM_MAX_MB * MEM_BUCKETS) var maxUsedBar = Buffer.alloc(maxUsedLen - minUsedLen) if (maxUsedLen > 0) { maxUsedBar.fill(']') } return minUsedBar.toString().blue + maxUsedBar.toString().red } function report () { var minhist = {} var maxhist = {} var stephist = {} var rtable = new Table({ head: ['min', 'min diff', 'max', 'max diff', 'steps', 'size'], chars: TABLE_CHARS, style: TABLE_STYLE }) var l var unfiltered = memRanges var filtered = unfiltered.filter(function (r, i) { if (argv.factor && i % argv.factor !== 0) { return false } if (argv.start && i < argv.start) { return false } if (argv.end && i > argv.end) { return false } return true }) filtered.forEach(function (r, i) { var minceil = Math.ceil(r[0]) minhist[minceil] = (minhist[minceil] || 0) + 1 var maxceil = Math.ceil(r[1]) maxhist[maxceil] = (maxhist[maxceil] || 0) + 1 var step = Math.ceil(r[2]) stephist[step] = (stephist[step] || 0) + 1 if (l) { rtable.push([ r[0], (r[0] - l[0]).toFixed(3), r[1], (r[1] - l[1]).toFixed(3), r[2], (r[1] - r[0]).toFixed(3), memoryBar(r[0], r[1]) ]) } else { rtable.push([ r[0], 0.00, r[1], 0.00, r[2], (r[1] - r[0]).toFixed(3), memoryBar(r[0], r[1]) ]) } l = r }) var k var minhead = [] var minbody = [] for (k in minhist) { minhead.push('<' + k) minbody.push(minhist[k]) } var mintable = new Table({ head: minhead, chars: TABLE_CHARS, style: TABLE_STYLE }) mintable.push(minbody) var maxhead = [] var maxbody = [] for (k in maxhist) { maxhead.push('<' + k) maxbody.push(maxhist[k]) } var maxtable = new Table({ head: maxhead, chars: TABLE_CHARS, style: TABLE_STYLE }) maxtable.push(maxbody) var stephead = [] var stepbody = [] for (k in stephist) { stephead.push(k) stepbody.push(stephist[k]) } var steptable = new Table({ head: stephead, chars: TABLE_CHARS, style: TABLE_STYLE }) steptable.push(stepbody) // ***************************************************************************** console.log() console.log('Heap Usage (MB)'.grey) rtable.toString().split('\n').forEach(function (l) { if (l.length > 0) { console.log(l) } }) console.log() console.log('Heap Used Lower Bound (MB)'.grey) mintable.toString().split('\n').forEach(function (l) { if (l.length > 0) { console.log(l) } }) console.log() console.log('Heap Used Upper Bound (MB)'.grey) maxtable.toString().split('\n').forEach(function (l) { if (l.length > 0) { console.log(l) } }) console.log() console.log('Iterations / GC'.grey) steptable.toString().split('\n').forEach(function (l) { if (l.length > 0) { console.log(l) } }) console.log() console.log('%s %d', 'Number of Iterations:'.grey, ITERATION_COUNT) console.log('%s %d', 'Number of GC executions (unfiltered):'.grey, unfiltered.length) console.log('%s %d', 'Number of GC executions (filtered):'.grey, filtered.length) console.log() } function readline (line) { if (line.trim().length === 0) { return line } var matches = line.match(MEM_MATCH) if (!matches || !matches[1]) { console.error('RegEx match failed on: |%s|', line, matches) process.exit(1) } var mem = parseFloat(matches[1]) if (memMin === undefined) { memMin = mem memCnt = 0 } if (memMax === undefined || mem > memMax) { memMax = mem memCnt++ } else { // this is where the magic happens // we will filter based on a factor memRanges.push([memMin, memMax, memCnt]) // reset memMin = mem memMax = mem memCnt = 0 } ITERATION_COUNT++ } // ***************************************************************************** // Event Listeners // ***************************************************************************** var lastLine process.stdin.on('data', function (chunk) { var i = 0 var j = 0 for (i = 0, j = chunk.indexOf('\n', i); j !== -1; i = j + 1, j = chunk.indexOf('\n', i)) { if (lastLine) { readline(lastLine + chunk.slice(i, j)) lastLine = undefined } else { readline(chunk.slice(i, j)) } } if (chunk.length > i) { lastLine = chunk.slice(i) } }) process.stdin.on('end', function () { report() }) // ***************************************************************************** // Run // ***************************************************************************** process.stdin.resume() process.stdin.setEncoding('utf8')