Setting up a simple runners cluster to parallelize calculations

This commit is contained in:
Nikolay Nemshilov 2016-11-06 16:54:27 +11:00
parent 97f1bb37f9
commit 7899c632f2
6 changed files with 119 additions and 13 deletions

View File

@ -24,6 +24,7 @@
"chai": "^3.5.0",
"chalk": "^1.1.3",
"co": "^4.6.0",
"co-mocha": "^1.1.3",
"mocha": "^3.1.2"
}
}

60
src/cluster.js Normal file
View File

@ -0,0 +1,60 @@
const cluster = require('cluster');
const { length: numCPUs } = require('os').cpus();
const { fork } = require('child_process');
const Runner = require('./runner');
const Layout = require('./layout');
const workers = [];
if (!process.env.CHILD_WORKER) {
while (workers.length < numCPUs) {
workers.push(fork(__dirname + '/cluster.js', { env: { CHILD_WORKER: 'yup' } }));
}
} else {
let runner;
process.on('message', msg => {
if (msg.cmd === 'reset') {
runner = new Runner(msg.text, msg.options);
} else if (msg.cmd === 'run') {
const result = runner.typeWith(new Layout(msg.name, msg.config));
process.send(Object.assign({}, msg, { cmd: 'result', result }));
}
});
}
module.exports = class Cluster {
constructor(text, options={}) {
workers.forEach(worker => {
worker.send({ cmd: 'reset', text, options });
worker.on('message', msg => this.receivedMessage(msg));
});
this.waiters = {};
}
*runCollection(layouts) {
const promises = layouts.map((layout, index) => {
const worker = workers[index % workers.length];
return this.scheduleRunWith(layout, worker);
});
return yield Promise.all(promises);
}
scheduleRunWith(layout, worker) {
return new Promise(resolve => {
const uuid = Date.now() / 10000 + Math.random();
this.waiters[uuid] = { resolve, worker };
worker.send(Object.assign({ cmd: 'run', uuid }, layout));
});
}
receivedMessage(msg) {
const { cmd, uuid, result, name, config } = msg;
if (cmd === 'result') {
const layout = new Layout(name, config);
const { worker, resolve } = this.waiters[uuid];
delete(this.waiters[uuid]);
resolve && resolve({ result, layout });
}
}
};

28
test/cluster_test.js Normal file
View File

@ -0,0 +1,28 @@
const Cluster = require('../src/cluster');
const { QWERTY, Dvorak, Colemak, Workman } = require('../src/presets');
const text = global.TEXT_FIXTUE;
const layouts = [ QWERTY, Dvorak, Colemak, Workman, QWERTY, Dvorak, Colemak, Workman ];
describe('Cluster', () => {
const cluster = new Cluster(text, {
effortLimit: 2000,
sameHandPenalty: 0.5,
sameFingerPenalty: 5
});
it('allows to run a bunch of layouts', function * () {
const results = yield cluster.runCollection(layouts);
const data = results.map(result => `${result.layout.name} - ${result.result.position}`);
expect(data.sort()).to.eql([
"Colemak - 744",
"Colemak - 744",
"Dvorak - 586",
"Dvorak - 586",
"QWERTY - 407",
"QWERTY - 407",
"Workman - 833",
"Workman - 833"
]);
});
});

View File

@ -1,2 +1,19 @@
const mocha = require('mocha');
const coMocha = require('co-mocha');
const { expect } = require('chai');
global.expect = expect;
coMocha(mocha);
global.TEXT_FIXTUE = `
A long time ago in a galaxy far, far away
It is a period of civil war. Rebel spaceships, striking from a
hidden base, have won their first victory against the evil Galactic Empire.
During the battle, Rebel spies managed to steal secret plans to the
Empire's ultimate weapon, the Death Star, an armored space station
with enough power to destroy an entire planet.
Pursued by the Empire's sinister agents, Princess Leia races home
aboard her starship, custodian of the stolen plans that can save her
people and restore freedom to the galaxy...
`;

View File

@ -1,17 +1,6 @@
const Runner = require('../src/runner');
const { QWERTY, Dvorak, Colemak, Workman } = require('../src/presets');
const text = `
A long time ago in a galaxy far, far away
It is a period of civil war. Rebel spaceships, striking from a
hidden base, have won their first victory against the evil Galactic Empire.
During the battle, Rebel spies managed to steal secret plans to the
Empire's ultimate weapon, the Death Star, an armored space station
with enough power to destroy an entire planet.
Pursued by the Empire's sinister agents, Princess Leia races home
aboard her starship, custodian of the stolen plans that can save her
people and restore freedom to the galaxy...
`;
const text = global.TEXT_FIXTUE;
describe('Runner', () => {
const runner = new Runner(text, {

View File

@ -148,7 +148,14 @@ cli-table@^0.3.1:
dependencies:
colors "1.0.3"
co@^4.6.0:
co-mocha:
version "1.1.3"
resolved "https://registry.yarnpkg.com/co-mocha/-/co-mocha-1.1.3.tgz#49bb9c85bcd17e3250f8b84b875dc76668bc41dc"
dependencies:
co "^4.0.0"
is-generator "^1.0.1"
co@^4.0.0, co@^4.6.0:
version "4.6.0"
resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184"
@ -360,6 +367,10 @@ inherits@~2.0.1, inherits@2:
version "2.0.3"
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de"
is-generator@^1.0.1:
version "1.0.3"
resolved "https://registry.yarnpkg.com/is-generator/-/is-generator-1.0.3.tgz#c14c21057ed36e328db80347966c693f886389f3"
is-my-json-valid@^2.12.4:
version "2.15.0"
resolved "https://registry.yarnpkg.com/is-my-json-valid/-/is-my-json-valid-2.15.0.tgz#936edda3ca3c211fd98f3b2d3e08da43f7b2915b"