Skip to content

Commit

Permalink
feat(benchmark): add a simple benchmark for context bindings
Browse files Browse the repository at this point in the history
  • Loading branch information
raymondfeng committed May 9, 2020
1 parent 08e0a56 commit 3f11e90
Show file tree
Hide file tree
Showing 4 changed files with 160 additions and 0 deletions.
2 changes: 2 additions & 0 deletions benchmark/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
"test": "lb-mocha \"dist/__tests__/**/*.js\"",
"prestart": "npm run build",
"benchmark:routing": "node ./dist/rest-routing/routing-table",
"benchmark:context": "node ./dist/context-binding/context-binding",
"start": "node ."
},
"author": "IBM Corp.",
Expand All @@ -32,6 +33,7 @@
"!*/__tests__"
],
"dependencies": {
"@loopback/context": "^3.7.0",
"@loopback/example-todo": "^3.3.0",
"@loopback/openapi-spec-builder": "^2.1.3",
"@loopback/rest": "^4.0.0",
Expand Down
71 changes: 71 additions & 0 deletions benchmark/src/context-binding/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
# Context binding benchmark

This directory contains a simple benchmarking to measure the performance of two
context bindings.

1. Use provider class

```ts
/**
* First option - use a provider class
*/
class GreetingProvider implements Provider<string> {
@inject('user')
private user: string;

value() {
return `Hello, ${this.user}`;
}
}
```

2. Use dynamic value

```ts
/**
* Second option - use a factory function
*/
const factory: ValueFactory = _ctx => {
const user = _ctx.getSync('user');
return `Hello, ${user}`;
};
```

3. Set up bindings

```ts
function setupContextBindings() {
const ctx = new Context();
ctx.bind('user').to('John');
ctx.bind('greeting1').toDynamicValue(factory);
ctx.bind('greeting2').toProvider(GreetingProvider);
return ctx;
}
```

## Basic use

```sh
npm run -s benchmark:context // default to 1000 | runs
```

For example:

```
npm run -s benchmark:context -- 1000 |0
```

## Base lines

| name | duration (ns) | count |
| -------- | ------------- | ------ |
| factory | 0,1168336 | 100 |
| provider | 0,3134085 | 100 |
| factory | 0,6276707 | 1000 |
| provider | 0,28293889 | 1000 |
| factory | 0,22999109 | 5000 |
| provider | 0,54420139 | 5000 |
| factory | 0,29685651 | 10000 |
| provider | 0,62901844 | 10000 |
| factory | 0,91520844 | 100000 |
| provider | 0,186124524 | 100000 |
84 changes: 84 additions & 0 deletions benchmark/src/context-binding/context-binding.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
// Copyright IBM Corp. 2018,2020. All Rights Reserved.
// Node module: @loopback/benchmark
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT

import {Context, inject, Provider, ValueFactory} from '@loopback/context';

/**
* First option - use a provider class
*/
class GreetingProvider implements Provider<string> {
@inject('user')
private user: string;

value() {
return `Hello, ${this.user}`;
}
}

/**
* Second option - use a factory function
*/
const factory: ValueFactory = _ctx => {
const user = _ctx.getSync('user');
return `Hello, ${user}`;
};

setupContextBindings();

function setupContextBindings() {
const ctx = new Context();
ctx.bind('user').to('John');
ctx.bind('greeting1').toDynamicValue(factory);
ctx.bind('greeting2').toProvider(GreetingProvider);
return ctx;
}

function runBenchmark(ctx: Context, count = 1000) {
let result1 = process.hrtime();

for (let i = 0; i < count; i++) {
ctx.getSync('greeting1');
}

result1 = process.hrtime(result1);

let result2 = process.hrtime();

for (let i = 0; i < count; i++) {
ctx.getSync('greeting2');
}

result2 = process.hrtime(result2);

console.log(
'%s %s %s',
'name'.padEnd(12),
'duration'.padStart(16),
'count'.padStart(8),
);
for (const r of [
{name: 'factory', duration: result1},
{name: 'provider', duration: result2},
]) {
console.log(
'%s %s %s',
`${r.name}`.padEnd(12),
`${r.duration}`.padStart(16),
`${count}`.padStart(8),
);
}
}

if (require.main === module) {
let tests = process.argv.slice(2);
if (!tests.length) {
tests = ['1000'];
}
const ctx = setupContextBindings();
tests.forEach(n => {
runBenchmark(ctx, +n);
console.log('\n');
});
}
3 changes: 3 additions & 0 deletions benchmark/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@
{
"path": "../packages/testlab/tsconfig.json"
},
{
"path": "../packages/context/tsconfig.json"
},
{
"path": "../examples/todo/tsconfig.json"
},
Expand Down

0 comments on commit 3f11e90

Please sign in to comment.