colyseus-server-stress-tester/index.js

119 lines
3.0 KiB
JavaScript

import enquirer from 'enquirer';
const { NumberPrompt, Select } = enquirer;
import ora from 'ora';
import { packageCounts, rps } from './received-packages.js';
import { Worker } from 'worker_threads';
import { dirname } from 'path';
import { fileURLToPath } from 'url';
import { Client } from './client.js';
const workerCounts = 4;
const testGroupWorkers = generateWorkers();
const {mainClient, numberOfPlayers} = await getConnectedWorkers();
await test();
function generateWorkers() {
return new Array(workerCounts).fill(undefined).map(() => new Worker(
dirname(fileURLToPath(import.meta.url)) + '/test-group.js',
));
}
async function test() {
const frequency = await new Select({
name: 'frequency',
message: 'frequency',
choices: [
{ name: '10tps', value: 10 },
{ name: '20tps', value: 20 },
{ name: '30tps', value: 30 },
{ name: '60tps', value: 60 },
]
}).run();
const spinner = ora('Testing...').start();
let times = 0;
let softStartup = 1;
setInterval(() => {
testGroupWorkers.forEach(worker => worker.postMessage({
type: 'testOnce',
limit: softStartup,
}));
mainClient.testOnce();
spinner.text = `${softStartup} player(s) sent ${++times} times,\trps:\t${rps}, counts: ${packageCounts}`;
}, 1000 / +/\d+/.exec(frequency)[0]);
const timer = setInterval(() => {
if (++softStartup >= numberOfPlayers) {
clearInterval(timer);
}
}, 100);
}
async function getConnectedWorkers() {
const numberOfPlayers = await new NumberPrompt({
name: 'number',
message: 'number of players',
}).run();
if (numberOfPlayers < 1) {
throw new Error('number of players must be greater than 0');
}
const spinner = ora('Connecting server and join room.').start();
const mainClient = new Client(0);
let assignedCursor = 1;
const groupSize = Math.ceil((numberOfPlayers - assignedCursor) / workerCounts);
await Promise.all(
testGroupWorkers.map(worker => new Promise(resolve => {
worker.on('message', message => {
if (message.type === 'workersGenerated') {
resolve();
}
});
worker.postMessage({
type: 'generateWorkers',
start: assignedCursor,
end: Math.min(assignedCursor += groupSize, numberOfPlayers),
});
}))
);
let connected = 1;
await mainClient.joinRoom();
spinner.text = `Connected ${connected}/${numberOfPlayers}.`;
await new Promise(resolve => {
testGroupWorkers.forEach(worker => {
worker.on('message', message => {
if (message.type === 'oneWorkerJoined') {
connected++;
spinner.text = `Connected ${connected}/${numberOfPlayers}.`;
if (connected === numberOfPlayers) {
resolve();
}
}
});
worker.on('joinRoomFailed', err => {
throw err;
})
worker.postMessage({
type: 'joinRoom',
});
});
})
spinner.succeed('Connected server and join room.');
return {mainClient, numberOfPlayers};
}