Skip to content

Commit

Permalink
Improve simple map benchmark (hazelcast#467)
Browse files Browse the repository at this point in the history
Also added a readme for the benchmark
  • Loading branch information
puzpuzpuz committed Mar 12, 2019
1 parent 63dea03 commit 2832fd5
Show file tree
Hide file tree
Showing 5 changed files with 142 additions and 56 deletions.
21 changes: 21 additions & 0 deletions benchmark/MapPutRunner.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
'use strict';

const REQ_COUNT = 50000;
const BATCH_SIZE = 100;

const Benchmark = require('./SimpleBenchmark');
const Client = require('../.').Client;

Client.newHazelcastClient()
.then((client) => client.getMap('default'))
.then((map) => {
const benchmark = new Benchmark({
nextOp: () => map.put('foo', 'bar'),
totalOpsCount: REQ_COUNT,
batchSize: BATCH_SIZE
});
return benchmark.run()
.then(() => map.destroy())
.then(() => map.client.shutdown());
})
.then(() => console.log('Benchmark finished'));
42 changes: 42 additions & 0 deletions benchmark/MapRandomOpRunner.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
'use strict';

const REQ_COUNT = 50000;
const BATCH_SIZE = 100;

const ENTRY_COUNT = 10 * 1000;
const VALUE_SIZE = 10000;
const GET_PERCENTAGE = 40;
const PUT_PERCENTAGE = 40;

let value_string = '';
for (let i = 0; i < VALUE_SIZE; i++) {
value_string = value_string + 'x';
}

function randomOp(map) {
const key = Math.random() * ENTRY_COUNT;
const opType = Math.floor(Math.random() * 100);
if (opType < GET_PERCENTAGE) {
return map.get(key);
} else if (opType < GET_PERCENTAGE + PUT_PERCENTAGE) {
return map.put(key, value_string);
}
return map.remove(key);
}

const Benchmark = require('./SimpleBenchmark');
const Client = require('../.').Client;

Client.newHazelcastClient()
.then((client) => client.getMap('default'))
.then((map) => {
const benchmark = new Benchmark({
nextOp: () => randomOp(map),
totalOpsCount: REQ_COUNT,
batchSize: BATCH_SIZE
});
return benchmark.run()
.then(() => map.destroy())
.then(() => map.client.shutdown());
})
.then(() => console.log('Benchmark finished'));
42 changes: 42 additions & 0 deletions benchmark/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# Simple benchmark for Hazelcast IMDG Node.js Client

A collection of simple benchmarks that run operations on Map in parallel, measure execution time and calculate throughput:
* `MapPutRunner` - runs `map.put('foo', 'bar')` operations.
* `MapRandomOpRunner` - runs randomly selected operations (`get`, `put`, `remove`).

## Running the benchmark

First, install dependencies and build the client:
```bash
npm install
```

Then, build the client (compile TypeScript):
```bash
npm run compile
```

Next, run at least one instance of IMDG. The most simple way to do it would be to use the [official Docker image](https://hub.docker.com/r/hazelcast/hazelcast/):
```bash
docker run -p 5701:5701 hazelcast/hazelcast:3.11.2
```

Finally, run the benchmark:
```bash
node benchmark/MapPutRunner.js
```

The benchmark will run and produce its results into the console:
```bash
[DefaultLogger] INFO at ConnectionAuthenticator: Connection to 172.17.0.2:5701 authenticated
[DefaultLogger] INFO at ClusterService: Members received.
[ Member {
address: Address { host: '172.17.0.2', port: 5701, type: 4 },
uuid: 'ea5ae364-9b0e-438d-bde6-e7592ca21c14',
isLiteMember: false,
attributes: {} } ]
[DefaultLogger] INFO at HazelcastClient: Client started
Took 1.058 seconds for 50000 requests
Ops/s: 47258.979206049145
Benchmark finished
```
37 changes: 37 additions & 0 deletions benchmark/SimpleBenchmark.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
'use strict';

class Benchmark {
constructor(config) {
this._nextOp = config.nextOp;
this.totalOpsCount = config.totalOpsCount;
this.batchSize = config.batchSize;
this.opsCount = 0;
}
// increments ops counter, starts a new op and returns its promise
nextOp() {
this.opsCount++;
return this._nextOp();
}
// chains next op once one of ops finishes to keep constant concurrency of ops
chainNext(op) {
return op.then(() => {
if (this.opsCount < this.totalOpsCount) {
return this.chainNext(this.nextOp());
}
});
}
run() {
// initial batch of ops (no-op promises)
const batch = new Array(this.batchSize).fill(Promise.resolve());
const start = new Date();
return Promise.all(batch.map(this.chainNext.bind(this)))
.then(() => {
const finish = new Date();
const tookSec = (finish - start) / 1000;
console.log(`Took ${tookSec} seconds for ${this.opsCount} requests`);
console.log(`Ops/s: ${this.opsCount / tookSec}`);
});
}
};

module.exports = Benchmark;
56 changes: 0 additions & 56 deletions benchmark/SimpleMapBenchmark.js

This file was deleted.

0 comments on commit 2832fd5

Please sign in to comment.