thunk(function * () { yield cli.connect(2345) yield cli.ping() const stream = cli.request() stream .on('error', (err) => ilog.error(Object.assign(err, { class: 'client stream error' }))) .on('data', (data) => { ilog.info(`client stream ${stream.id} data: ${data.toString()}`) }) .on('end', () => { ilog.info(`client stream ${stream.id} ended`) cli.close() }) .on('finish', () => { ilog.info(`client stream ${stream.id} finished`) }) yield (done) => stream.write('hello, QUIC', done) let i = 0 while (i <= 99) { yield thunk.delay(100) yield (done) => stream.write(`${i++}`, done) } stream.end() yield (done) => cli.once('close', done) yield server.close() })(ilog.error)
return thunk.delay()(function () { console.log('Test ' + test.name + '...') test.startTime = Date.now() test.cycles = test.error = test.endTime = test.ops = null var cycleQueue = [] var testFn = test.test forEach(cycles, function (_, index) { cycleQueue.push(thunk.delay(), function (done) { var time = Date.now() // 异步执行测试的每一个循环 thunk(testFn)(function (error) { if (error) throw error test.cycles = index + 1 if (ctx._events.cycle) { ctx.trigger('cycle', {name: test.name, cycle: index + 1, time: Date.now() - time}) } })(done) }) }) return thunk.seq(cycleQueue)(function (error) { if (error == null) test.endTime = Date.now() else { test.error = error ctx.trigger('error', {name: test.name, error: error}) } }) })(callback)
function gulpSequence () { if (!gulp) gulp = require('gulp') const BREAKER = {} const args = slice.call(arguments) var done = args[args.length - 1] if (typeof done === 'function') args.pop() else done = null if (!args.length) { throw new Error('No tasks were provided to gulp-sequence!') } const runSequence = thunk.seq(args.filter(function (taskName) { // filter falsely taskName return taskName }).map(function (task) { return function (callback) { if (!Array.isArray(task)) task = [task] function successListener (e) { let index = task.indexOf(e.task) if (index < 0) return task[index] = BREAKER for (let i = 0; i < task.length; i++) { if (task[i] !== BREAKER) return } removeListener() callback() } function errorListener (e) { if (!e.err || task.indexOf(e.task) < 0) return removeListener() callback(e.err) } function removeListener () { gulp.removeListener('task_stop', successListener) .removeListener('task_not_found', errorListener) .removeListener('task_recursion', errorListener) .removeListener('task_err', errorListener) } gulp .on('task_stop', successListener) .on('task_not_found', errorListener) .on('task_recursion', errorListener) .on('task_err', errorListener) .start(task.slice()) } })) return done ? runSequence(done) : runSequence }
forEach(cycles, function (_, index) { cycleQueue.push(thunk.delay(), function (done) { var time = Date.now() // 异步执行测试的每一个循环 thunk(testFn)(function (error) { if (error) throw error test.cycles = index + 1 if (ctx._events.cycle) { ctx.trigger('cycle', {name: test.name, cycle: index + 1, time: Date.now() - time}) } })(done) }) })
run (cycles) { const ctx = this const list = ctx._list cycles = cycles >= 1 ? Math.floor(cycles) : 10 if (!ctx._events.error) { // 如果未定义,则使用默认的 error 监听 ctx.on('error', function (e) { console.error(e.name + ' error: ' + e.error) }) } if (!ctx._events.complete) { // 如果未定义,则使用默认的 complete 监听 ctx.on('complete', function (e) { console.log('\nJSBench Results:') forEach(e.ranking, function (test) { console.log(test.name + ': ' + test.message) }) console.log(e.result) }) } // 按顺序串行执行各个测试 console.log('\nJSBench Start, ' + cycles + ' cycles:') return thunk.seq(list.map(function (test) { // 异步执行每一个测试 return function (callback) { return thunk.delay()(function () { console.log('Test ' + test.name + '...') test.startTime = Date.now() test.cycles = test.error = test.endTime = test.ops = null var cycleQueue = [] var testFn = test.test forEach(cycles, function (_, index) { cycleQueue.push(thunk.delay(), function (done) { var time = Date.now() // 异步执行测试的每一个循环 thunk(testFn)(function (error) { if (error) throw error test.cycles = index + 1 if (ctx._events.cycle) { ctx.trigger('cycle', {name: test.name, cycle: index + 1, time: Date.now() - time}) } })(done) }) }) return thunk.seq(cycleQueue)(function (error) { if (error == null) test.endTime = Date.now() else { test.error = error ctx.trigger('error', {name: test.name, error: error}) } }) })(callback) } }))(function (error) { if (error) { ctx.trigger('error', {name: 'JSBench', error: error}) throw error } var result var base var ms var ranking = list.slice() // 测试完毕,计算结果 forEach(list, function (test) { if (test.error) test.message = test.error else { ms = (test.endTime - test.startTime) / test.cycles test.ops = 1000 / ms test.message = test.cycles + ' cycles, ' + ms + ' ms/cycle, ' + test.ops.toFixed(3) + ' ops' } }) // 对结果进行排序对比 ranking.sort(function (a, b) { return a.ops - b.ops }) forEach(ranking, function (test) { if (!test.ops) return if (base) result += ' ' + test.name + ': ' + (test.ops * 100 / base).toFixed(2) + '%;' else { base = test.ops result = '\n' + test.name + ': 100%;' } }) ctx.trigger('complete', {result: result, ranking: ranking}) console.log('\nJSBench Completed!') return ranking }) }