@phenixrts/aerospike
Version:
Aerospike Client Library
294 lines (247 loc) • 7.18 kB
JavaScript
// *****************************************************************************
// 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.
// *****************************************************************************
// *****************************************************************************
// node inspect.js -h
// *****************************************************************************
var spawn = require('child_process').spawn
var cluster = require('cluster')
var yargs = require('yargs')
var os = require('os')
var stats = require('./stats')
// *****************************************************************************
// Options Parsing
// *****************************************************************************
var argp = yargs
.usage('$0 [options]')
.options({
help: {
boolean: true,
describe: 'Display this message.'
},
host: {
alias: 'h',
default: '127.0.0.1',
describe: 'Aerospike database address.'
},
port: {
alias: 'p',
default: 3000,
describe: 'Aerospike database port.'
},
timeout: {
alias: 't',
default: 10,
describe: 'Timeout in milliseconds.'
},
log: {
alias: 'l',
default: 1,
describe: 'Log level [0-5].'
},
namespace: {
alias: 'n',
default: 'test',
describe: 'Key namespace.'
},
set: {
alias: 's',
default: 'demo',
describe: 'Key set.'
},
reads: {
alias: 'R',
default: 1,
describe: 'The read in the read/write ratio.'
},
writes: {
alias: 'W',
default: 1,
describe: 'The write in the read/write ratio.'
},
keyrange: {
alias: 'K',
default: 1000,
describe: 'The number of keys to use.'
}
})
var argv = argp.argv
if (argv.help === true) {
argp.showHelp()
process.exit()
}
if (!cluster.isMaster) {
console.error('main.js must not run as a child process.')
process.exit()
}
// *****************************************************************************
// Globals
// *****************************************************************************
var cpus = os.cpus()
var P_MIN = 1
var P_MAX = cpus.length
var P_STEP = 1
var I_MIN = 1
var I_MAX = 1
var I_STEP = 1
var O_MIN = 1
var O_MAX = 100
var O_STEP = 8
// *****************************************************************************
// Functions
// *****************************************************************************
var results = []
var errors = []
function reportStep (p, i, o, code, stdout, stderr) {
console.log('processes: %d, iterations: %d, operations: %d, status: %d', p, i, o, code)
console.log()
var result
if (code === 0) {
result = JSON.parse(stdout)
console.log(' tps (per process):')
console.log(' min: %d, max: %d, mean: %d',
result.tps.min,
result.tps.max,
result.tps.mean
)
console.log(' times (ms):')
console.log(' min: %d, max: %d, mean: %d',
result.times.min.toFixed(2),
result.times.max.toFixed(2),
result.times.mean.toFixed(2)
)
console.log(' duration:')
stats.print_histogram(result.durations, console.log, ' ')
console.log(' status codes:')
stats.print_histogram(result.status_codes, console.log, ' ')
results.push(result)
} else {
stderr.split('\n').forEach(function (l) {
console.log(' error: %s', l)
})
errors.push([p, i, o, code, stderr])
}
console.log()
}
function reportFinal () {
console.log()
console.log('SUMMARY')
console.log()
var matched = results.filter(function (res) {
var ops = res.operations
return (res.durations['<= 1'] / ops * 100).toFixed(0) >= 90 &&
(res.durations['> 1'] / ops * 100).toFixed(0) <= 10 &&
(res.durations['> 2'] / ops * 100).toFixed(0) <= 2 &&
(res.durations['<= 1'] + res.durations['> 1'] + res.durations['> 2'] === ops)
})
matched.forEach(function (res) {
console.log(' processes: %d, iterations: %d, operations: %d',
res.configuration.processes,
res.configuration.iterations,
res.configuration.operations
)
console.log(' tps: {min: %d, max: %d, avg: %d}',
res.tps.min,
res.tps.max,
res.tps.mean
)
console.log(' time: {min: %d, max: %d, avg: %d}',
res.times.min.toFixed(2),
res.times.max.toFixed(2),
res.times.mean.toFixed(2)
)
console.log(' duration:')
stats.print_histogram(res.durations, console.log, ' ')
})
var groupOps = {}
matched.forEach(function (res) {
var ops = res.configuration.operations
var group = (groupOps[ops] || [])
group.push(res)
groupOps[ops] = group
})
console.log()
console.log()
for (var k in groupOps) {
var ops = groupOps[k]
console.log('operations: %d', k)
for (var o = 0; o < ops.length; o++) {
var op = ops[o]
console.log(' p: %d, tps: {l: %d, u: %d, m: %d}, time: {l: %d, u: %d, m: %d}, dur: {0: %d, 1: %d, 2: %d}',
op.configuration.processes,
op.tps.min,
op.tps.max,
op.tps.mean,
op.times.min.toFixed(2),
op.times.max.toFixed(2),
op.times.mean.toFixed(2),
op.durations['<= 1'],
op.durations['> 1'],
op.durations['> 2']
)
}
}
console.log()
var opsHist = {}
matched.forEach(function (res) {
var ops = res.configuration.operations
opsHist[ops] = (opsHist[ops] || 0) + 1
})
console.log()
console.log('Number of Concurrent Transactions:')
stats.print_histogram(opsHist, console.log, ' ')
console.log()
}
function exec (p, i, o) {
var stdout = Buffer.alloc(0)
var stderr = Buffer.alloc(0)
var prog = 'node'
var args = ['main.js',
'-h', argv.host, '-p', argv.port, '-t', argv.timeout,
'-n', argv.namespace, '-s', argv.set,
'-R', argv.reads, '-W', argv.writes, '-K', argv.keyrange,
'-P', p, '-I', i, '-O', o,
'--silent', '--json'
]
var proc = spawn(prog, args)
proc.stdout.on('data', function (data) {
stdout = Buffer.concat([stdout, data])
})
proc.stderr.on('data', function (data) {
stderr = Buffer.concat([stderr, data])
})
proc.on('close', function (code) {
reportStep(p, i, o, code, stdout.toString(), stderr.toString())
step(p, i, o)
})
}
function step (p, i, o) {
o += O_STEP
if (o > O_MAX) {
i += I_STEP
o = O_MIN
}
if (i > I_MAX) {
p += P_STEP
i = I_MIN
o = O_MIN
}
if (p > P_MAX) {
reportFinal()
return
}
return exec(p, i, o)
}
exec(P_MIN, I_MIN, O_MIN)