Skip to content

Commit

Permalink
providing the option to do a setup and teardown (#18)
Browse files Browse the repository at this point in the history
  • Loading branch information
Idrinth authored Dec 17, 2020
1 parent ab1efc0 commit dcbdd53
Show file tree
Hide file tree
Showing 6 changed files with 143 additions and 38 deletions.
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "@idrinth/api-bench",
"description": "A library to benchmark apis, no matter if rest or soap",
"license": "MIT",
"version": "1.2.7",
"version": "1.2.8",
"homepage": "https://github.com/Idrinth/api-bench",
"repository": {
"type": "git",
Expand Down
99 changes: 73 additions & 26 deletions src/executor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,6 @@ import {
import {
FinishedSet,
} from './finished-set';
import {
Task,
} from './task';
import {
ResultSet,
} from './result-set';
Expand All @@ -22,8 +19,10 @@ import {
import Reporter from './reporter/reporter';
import * as Progress from 'cli-progress';
import validateTasks from './validate-tasks';
import Job from './job';

const EMPTY = 0;
const SINGLE = 1;

export interface WorkerConstructor {
new(path: string);
Expand All @@ -42,7 +41,7 @@ export interface Thread {
const executor = (
threads: number,
repetitions: number,
tasks: Array<Task>,
job: Job,
resultHandler: Reporter,
logger: Logger,
Worker: WorkerConstructor,
Expand All @@ -51,7 +50,7 @@ const executor = (
const path = `${ __dirname }/../worker/${ file }.js`;
return new Worker(realpathSync(path,),);
};
validateTasks(repetitions, threads, tasks,);
validateTasks(repetitions, threads, job.main,);
const validator: Thread = buildWorker('validator',);
const calculator: Thread = buildWorker('calculator',);
const bar = new Progress.SingleBar({
Expand All @@ -69,12 +68,21 @@ const executor = (
'initializing tasks to have '+
`${ threads } Threads x ${ repetitions } Repetitions todos`,
);
for (const task of tasks) {
for (const task of job.main) {
for (let i=0; i<threads*repetitions; i ++) {
internalTasks.push(task,);
}
}
bar.start(internalTasks.length + internalTasks.length + tasks.length, EMPTY,);
const barLength = (() => {
const main = job.main.length * repetitions * threads;
const mainFactor = SINGLE + job.afterEach.length + job.beforeEach.length;
const validation = job.main.length * repetitions * threads;
const calculation = job.main.length;
const pre = job.before.length + job.beforeTask.length * job.main.length;
const post = job.after.length + job.afterTask.length * job.main.length;
return pre + main * mainFactor + post + validation + calculation;
})();
bar.start(barLength, EMPTY,);
calculator.on('message', (data: FinishedSet,) => {
finished[data.id] = data;
logger.debug(`Analyzation of ${ data.id } finished`,);
Expand Down Expand Up @@ -106,25 +114,64 @@ const executor = (
logger.info('Validations done',);
}
},);
logger.debug(`starting up ${ threads } Workers`,);
for (let j=0; j<threads; j ++) {
workers.push(buildWorker('webrequest',),);
workers[j].on('message', (data: Result,) => {
logger.debug(`Starting validation of ${ data.id }`,);
checking ++;
bar.increment();
validator.postMessage(data,);
if (internalTasks.length > EMPTY) {
logger.debug('Starting next request',);
workers[j].postMessage(internalTasks.shift(),);
return;
}
active --;
workers[j].terminate();
logger.info('All requests done, terminating thread',);
},);
active ++;
workers[j].postMessage(internalTasks.shift(),);
const before = buildWorker('webrequest',);
const after = buildWorker('webrequest',);
const startMain = () => {
logger.debug(`starting up ${ threads } Workers`,);
for (let j=0; j<threads; j ++) {
workers.push(buildWorker('webrequest',),);
workers[j].on('message', (data: Result,) => {
logger.debug(`Starting validation of ${ data.id }`,);
checking ++;
bar.increment();
validator.postMessage(data,);
if (internalTasks.length > EMPTY) {
logger.debug('Starting next request',);
workers[j].postMessage(internalTasks.shift(),);
return;
}
active --;
workers[j].terminate();
logger.info('All requests done, terminating thread',);
if (active === EMPTY) {
if (job.after.length > EMPTY) {
logger.debug('Starting next request',);
after.postMessage(job.after.shift(),);
} else {
after.terminate();
before.terminate();
}
}
},);
active ++;
workers[j].postMessage(internalTasks.shift(),);
}
};
after.on('message', () => {
bar.increment();
if (job.after.length > EMPTY) {
logger.debug('Starting next request',);
after.postMessage(job.after.shift(),);
return;
}
after.terminate();
before.terminate();
},);
before.on('message', () => {
bar.increment();
if (job.before.length > EMPTY) {
logger.debug('Starting next request',);
before.postMessage(job.before.shift(),);
return;
}
before.terminate();
startMain();
},);
if (job.before.length > EMPTY) {
logger.debug('Starting next request',);
before.postMessage(job.before.shift(),);
} else {
startMain();
}
};

Expand Down
14 changes: 14 additions & 0 deletions src/job.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import {
Task,
} from './task';

interface Job {
before: Task[],
beforeTask: Task[],
beforeEach: Task[],
main: Task[],
afterEach: Task[],
afterTask: Task[],
after: Task[],
}
export default Job;
30 changes: 26 additions & 4 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,20 +13,42 @@ import executor from './executor';
import {
Worker,
} from 'worker_threads';
import Job from './job';

/* eslint max-params:0 */
export default (
const run = (
threads: number,
repetitions: number,
tasks: Array<Task>,
job: Job,
resultHandler?: Reporter|undefined,
logger?: Logger|undefined,
): void => {
) => {
if (typeof logger === 'undefined') {
logger = new NullLogger();
}
if (typeof resultHandler === 'undefined') {
resultHandler = defaultReporter;
}
executor(threads, repetitions, tasks, resultHandler, logger, Worker,);
executor(threads, repetitions, job, resultHandler, logger, Worker,);
};

/* eslint max-params:0 */
export default (
threads: number,
repetitions: number,
tasks: Array<Task>,
resultHandler?: Reporter|undefined,
logger?: Logger|undefined,
): void => {
const job: Job = {
before: [],
beforeTask: [],
beforeEach: [],
main: tasks,
afterEach: [],
afterTask: [],
after: [],
};
run(threads, repetitions, job, resultHandler, logger,);
};
//export run;
34 changes: 28 additions & 6 deletions test/executor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import {
import {
realpathSync,
} from 'fs';
import Job from '../src/job';

// eslint-disable-next-line @typescript-eslint/no-empty-function
const NOOP = () => {};
Expand Down Expand Up @@ -126,34 +127,55 @@ class FakeWorker implements Thread {
describe('executor', () => {
const repeats = 2;
const threads = 3;
const setup = 2;
const tasks = [ <Task> {
id: 'test',
}, ];
const noJob: Job = {
before: [],
beforeTask: [],
beforeEach: [],
main: [],
afterEach: [],
afterTask: [],
after: [],
};
const job: Job = {
...noJob,
main: tasks,
};
const once = 1;
it('should be a function', () => {
expect(executor,).to.be.a('function',);
},);
it('should not try to execute no tasks(0 tasks)', () => {
expect(
() => executor(threads, repeats, [], NOOP, new NullLogger(), FakeWorker,),
() => executor(
threads,
repeats,
noJob,
NOOP,
new NullLogger(),
FakeWorker,
),
).to.throw('Can\'t measure no tasks.',);
},);
it('should not try to execute no tasks(0 threads)', () => {
expect(
() => executor(NONE, repeats, tasks, NOOP, new NullLogger(), FakeWorker,),
() => executor(NONE, repeats, job, NOOP, new NullLogger(), FakeWorker,),
).to.throw('Can\'t measure no tasks.',);
},);
it('should not try to execute no tasks (0 repeats)', () => {
expect(
() => executor(threads, NONE, tasks, NOOP, new NullLogger(), FakeWorker,),
() => executor(threads, NONE, job, NOOP, new NullLogger(), FakeWorker,),
).to.throw('Can\'t measure no tasks.',);
},);
it('should execute all tasks', (done,) => {
expect(
() => executor(
threads,
repeats,
tasks,
job,
() => done(),
new NullLogger(),
FakeWorker,
Expand All @@ -164,14 +186,14 @@ describe('executor', () => {
const output = {};
output[realpathSync('./worker/calculator.js',)] = once;
output[realpathSync('./worker/validator.js',)] = once;
output[realpathSync('./worker/webrequest.js',)] = threads;
output[realpathSync('./worker/webrequest.js',)] = threads + setup;
expect(FakeWorker.built,).to.deep.equal(output,);
},);
it('should have shut down the right workers', () => {
const output = {};
output[realpathSync('./worker/calculator.js',)] = once;
output[realpathSync('./worker/validator.js',)] = once;
output[realpathSync('./worker/webrequest.js',)] = threads;
output[realpathSync('./worker/webrequest.js',)] = threads + setup;
expect(FakeWorker.terminated,).to.deep.equal(output,);
},);
},);

0 comments on commit dcbdd53

Please sign in to comment.