feat: 多线程压测。

This commit is contained in:
Ivan Li 2022-08-04 09:56:05 +08:00
commit 52bb816282
10 changed files with 701 additions and 0 deletions

12
.editorconfig Normal file
View File

@ -0,0 +1,12 @@
# EditorConfig is awesome: https://EditorConfig.org
# top-most EditorConfig file
root = true
[*]
indent_style = space
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = false
insert_final_newline = false

130
.gitignore vendored Normal file
View File

@ -0,0 +1,130 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*
.pnpm-debug.log*
# Diagnostic reports (https://nodejs.org/api/report.html)
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
*.lcov
# nyc test coverage
.nyc_output
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
bower_components
# node-waf configuration
.lock-wscript
# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules/
jspm_packages/
# Snowpack dependency directory (https://snowpack.dev/)
web_modules/
# TypeScript cache
*.tsbuildinfo
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Optional stylelint cache
.stylelintcache
# Microbundle cache
.rpt2_cache/
.rts2_cache_cjs/
.rts2_cache_es/
.rts2_cache_umd/
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variable files
.env
.env.development.local
.env.test.local
.env.production.local
.env.local
# parcel-bundler cache (https://parceljs.org/)
.cache
.parcel-cache
# Next.js build output
.next
out
# Nuxt.js build / generate output
.nuxt
dist
# Gatsby files
.cache/
# Comment in the public line in if your project uses Gatsby and not Next.js
# https://nextjs.org/blog/next-9-1#public-directory-support
# public
# vuepress build output
.vuepress/dist
# vuepress v2.x temp and cache directory
.temp
.cache
# Docusaurus cache and generated files
.docusaurus
# Serverless directories
.serverless/
# FuseBox cache
.fusebox/
# DynamoDB Local files
.dynamodb/
# TernJS port file
.tern-port
# Stores VSCode versions used for testing VSCode extensions
.vscode-test
# yarn v2
.yarn/cache
.yarn/unplugged
.yarn/build-state.yml
.yarn/install-state.gz
.pnp.*

1
.npmrc Normal file
View File

@ -0,0 +1 @@
shamefully-hoist=true

44
client.js Normal file
View File

@ -0,0 +1,44 @@
import * as Colyseus from "colyseus.js";
import { logError, writeLine } from "./logger.js";
import { markReceive } from "./received-packages.js";
export class Client {
client;
room;
index;
packageIndex = 0;
constructor(index) {
this.index = index;
}
async joinRoom() {
this.client = new Colyseus.Client('wss://api-meta.sequenxe.com/socket');
this.room = await this.client.joinOrCreate("my_room");
this.room.onStateChange((state) => {
if (this.index !== 0) {
return;
}
markReceive();
writeLine(state);
});
this.room.onError((code, message) => {
logError('error:', code, message);
})
}
testOnce() {
this.room.send("updatePlayer", {
x: +Math.random().toFixed(1),
y: +Math.random().toFixed(1),
z: +Math.random().toFixed(1),
rotationX: +Math.random().toFixed(1),
rotationY: +Math.random().toFixed(1),
rotationZ: +Math.random().toFixed(1),
animation: Math.random().toFixed(1),
nickname: Math.random().toFixed(1),
characterKey: `${this.index}#${this.packageIndex++}`,
});
}
}

118
index.js Normal file
View File

@ -0,0 +1,118 @@
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};
}

19
logger.js Normal file
View File

@ -0,0 +1,19 @@
import { createWriteStream } from 'fs';
import { fileURLToPath } from 'url';
import { dirname } from 'path';
const statefileStream = createWriteStream(
`${dirname(fileURLToPath(import.meta.url))}/logs/state.log`,
{ flags: 'w' },
);
const erroutfileStream = createWriteStream(
`${dirname(fileURLToPath(import.meta.url))}/logs/error.log`,
{ flags: 'w' },
);
export const writeLine = (obj) => {
statefileStream.write(JSON.stringify(obj) + '\n');
}
export const logError = (...args) => {
erroutfileStream.write(JSON.stringify(args) + '\n');
}

22
package.json Normal file
View File

@ -0,0 +1,22 @@
{
"name": "gallery_server_tester",
"version": "1.0.0",
"description": "",
"main": "index.js",
"type": "module",
"scripts": {
"start": "node index.js"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"@tweenjs/tween.js": "^18.6.4",
"colyseus.js": "^0.14.13",
"enquirer": "^2.3.6",
"log-update": "^5.0.1",
"ora": "^6.1.2",
"ramda": "^0.28.0",
"ws": "^8.8.1"
}
}

308
pnpm-lock.yaml Normal file
View File

@ -0,0 +1,308 @@
lockfileVersion: 5.4
specifiers:
'@tweenjs/tween.js': ^18.6.4
colyseus.js: ^0.14.13
enquirer: ^2.3.6
log-update: ^5.0.1
ora: ^6.1.2
ramda: ^0.28.0
ws: ^8.8.1
dependencies:
'@tweenjs/tween.js': 18.6.4
colyseus.js: 0.14.13
enquirer: 2.3.6
log-update: 5.0.1
ora: 6.1.2
ramda: 0.28.0
ws: 8.8.1
packages:
/@colyseus/schema/1.0.36:
resolution: {integrity: sha512-9LHDELuDCcp/EbZUsgdcekOPINvq+5Dn/Jooq+I2jHymU1zqzzwoqNq9+YYkuvI70OIJ1esPurcMTA2+o7brYg==}
hasBin: true
dev: false
/@tweenjs/tween.js/18.6.4:
resolution: {integrity: sha512-lB9lMjuqjtuJrx7/kOkqQBtllspPIN+96OvTCeJ2j5FEzinoAXTdAMFnDAQT1KVPRlnYfBrqxtqP66vDM40xxQ==}
dev: false
/ansi-colors/4.1.3:
resolution: {integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==}
engines: {node: '>=6'}
dev: false
/ansi-escapes/5.0.0:
resolution: {integrity: sha512-5GFMVX8HqE/TB+FuBJGuO5XG0WrsA6ptUqoODaT/n9mmUaZFkqnBueB4leqGBCmrUHnCnC4PCZTCd0E7QQ83bA==}
engines: {node: '>=12'}
dependencies:
type-fest: 1.4.0
dev: false
/ansi-regex/6.0.1:
resolution: {integrity: sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==}
engines: {node: '>=12'}
dev: false
/ansi-styles/6.1.0:
resolution: {integrity: sha512-VbqNsoz55SYGczauuup0MFUyXNQviSpFTj1RQtFzmQLk18qbVSpTFFGMT293rmDaQuKCT6InmbuEyUne4mTuxQ==}
engines: {node: '>=12'}
dev: false
/base64-js/1.5.1:
resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==}
dev: false
/bl/5.0.0:
resolution: {integrity: sha512-8vxFNZ0pflFfi0WXA3WQXlj6CaMEwsmh63I1CNp0q+wWv8sD0ARx1KovSQd0l2GkwrMIOyedq0EF1FxI+RCZLQ==}
dependencies:
buffer: 6.0.3
inherits: 2.0.4
readable-stream: 3.6.0
dev: false
/buffer/6.0.3:
resolution: {integrity: sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==}
dependencies:
base64-js: 1.5.1
ieee754: 1.2.1
dev: false
/chalk/5.0.1:
resolution: {integrity: sha512-Fo07WOYGqMfCWHOzSXOt2CxDbC6skS/jO9ynEcmpANMoPrD+W1r1K6Vx7iNm+AQmETU1Xr2t+n8nzkV9t6xh3w==}
engines: {node: ^12.17.0 || ^14.13 || >=16.0.0}
dev: false
/cli-cursor/4.0.0:
resolution: {integrity: sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==}
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
dependencies:
restore-cursor: 4.0.0
dev: false
/cli-spinners/2.7.0:
resolution: {integrity: sha512-qu3pN8Y3qHNgE2AFweciB1IfMnmZ/fsNTEE+NOFjmGB2F/7rLhnhzppvpCnN4FovtP26k8lHyy9ptEbNwWFLzw==}
engines: {node: '>=6'}
dev: false
/clone/1.0.4:
resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==}
engines: {node: '>=0.8'}
dev: false
/colyseus.js/0.14.13:
resolution: {integrity: sha512-2z1jgOfozQ02gLG5RtTHpk9VZur2b7U4KI9NNldjOZmfc2DZeKejdcKchBTwiDcSwwJQQ4SSOfVUhOcBMILDqA==}
engines: {node: '>= 12.x'}
dependencies:
'@colyseus/schema': 1.0.36
httpie: 2.0.0-next.13
nanoevents: 5.1.13
notepack.io: 2.3.0
tslib: 2.4.0
dev: false
/defaults/1.0.3:
resolution: {integrity: sha512-s82itHOnYrN0Ib8r+z7laQz3sdE+4FP3d9Q7VLO7U+KRT+CR0GsWuyHxzdAY82I7cXv0G/twrqomTJLOssO5HA==}
dependencies:
clone: 1.0.4
dev: false
/eastasianwidth/0.2.0:
resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==}
dev: false
/emoji-regex/9.2.2:
resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==}
dev: false
/enquirer/2.3.6:
resolution: {integrity: sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==}
engines: {node: '>=8.6'}
dependencies:
ansi-colors: 4.1.3
dev: false
/httpie/2.0.0-next.13:
resolution: {integrity: sha512-KbKOnq8wt0hVEfteYCSnEsPgzaWxcVc4qZ4OaDU9mVOYLRo3XChjWs3MiuRgFu5y+4JDo7sDKdKzkAn1ljQYFA==}
engines: {node: '>=10'}
dev: false
/ieee754/1.2.1:
resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==}
dev: false
/inherits/2.0.4:
resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==}
dev: false
/is-fullwidth-code-point/4.0.0:
resolution: {integrity: sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==}
engines: {node: '>=12'}
dev: false
/is-interactive/2.0.0:
resolution: {integrity: sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==}
engines: {node: '>=12'}
dev: false
/is-unicode-supported/1.2.0:
resolution: {integrity: sha512-wH+U77omcRzevfIG8dDhTS0V9zZyweakfD01FULl97+0EHiJTTZtJqxPSkIIo/SDPv/i07k/C9jAPY+jwLLeUQ==}
engines: {node: '>=12'}
dev: false
/log-symbols/5.1.0:
resolution: {integrity: sha512-l0x2DvrW294C9uDCoQe1VSU4gf529FkSZ6leBl4TiqZH/e+0R7hSfHQBNut2mNygDgHwvYHfFLn6Oxb3VWj2rA==}
engines: {node: '>=12'}
dependencies:
chalk: 5.0.1
is-unicode-supported: 1.2.0
dev: false
/log-update/5.0.1:
resolution: {integrity: sha512-5UtUDQ/6edw4ofyljDNcOVJQ4c7OjDro4h3y8e1GQL5iYElYclVHJ3zeWchylvMaKnDbDilC8irOVyexnA/Slw==}
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
dependencies:
ansi-escapes: 5.0.0
cli-cursor: 4.0.0
slice-ansi: 5.0.0
strip-ansi: 7.0.1
wrap-ansi: 8.0.1
dev: false
/mimic-fn/2.1.0:
resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==}
engines: {node: '>=6'}
dev: false
/nanoevents/5.1.13:
resolution: {integrity: sha512-JFAeG9fp0QZnRoESHjkbVFbZ9BkOXkkagUVwZVo/pkSX+Fq1VKlY+5og/8X9CYc6C7vje/CV+bwJ5M2X0+IY9Q==}
engines: {node: '>=6.0.0'}
dev: false
/notepack.io/2.3.0:
resolution: {integrity: sha512-9RiFDxeydHsWOqdthRUck2Kd4UW2NzVd2xxOulZiQ9mvge6ElsHXLpwD3HEJyql6sFEnEn/eMO7HSdS0M5mWkA==}
dev: false
/onetime/5.1.2:
resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==}
engines: {node: '>=6'}
dependencies:
mimic-fn: 2.1.0
dev: false
/ora/6.1.2:
resolution: {integrity: sha512-EJQ3NiP5Xo94wJXIzAyOtSb0QEIAUu7m8t6UZ9krbz0vAJqr92JpcK/lEXg91q6B9pEGqrykkd2EQplnifDSBw==}
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
dependencies:
bl: 5.0.0
chalk: 5.0.1
cli-cursor: 4.0.0
cli-spinners: 2.7.0
is-interactive: 2.0.0
is-unicode-supported: 1.2.0
log-symbols: 5.1.0
strip-ansi: 7.0.1
wcwidth: 1.0.1
dev: false
/ramda/0.28.0:
resolution: {integrity: sha512-9QnLuG/kPVgWvMQ4aODhsBUFKOUmnbUnsSXACv+NCQZcHbeb+v8Lodp8OVxtRULN1/xOyYLLaL6npE6dMq5QTA==}
dev: false
/readable-stream/3.6.0:
resolution: {integrity: sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==}
engines: {node: '>= 6'}
dependencies:
inherits: 2.0.4
string_decoder: 1.3.0
util-deprecate: 1.0.2
dev: false
/restore-cursor/4.0.0:
resolution: {integrity: sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==}
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
dependencies:
onetime: 5.1.2
signal-exit: 3.0.7
dev: false
/safe-buffer/5.2.1:
resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==}
dev: false
/signal-exit/3.0.7:
resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==}
dev: false
/slice-ansi/5.0.0:
resolution: {integrity: sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==}
engines: {node: '>=12'}
dependencies:
ansi-styles: 6.1.0
is-fullwidth-code-point: 4.0.0
dev: false
/string-width/5.1.2:
resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==}
engines: {node: '>=12'}
dependencies:
eastasianwidth: 0.2.0
emoji-regex: 9.2.2
strip-ansi: 7.0.1
dev: false
/string_decoder/1.3.0:
resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==}
dependencies:
safe-buffer: 5.2.1
dev: false
/strip-ansi/7.0.1:
resolution: {integrity: sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==}
engines: {node: '>=12'}
dependencies:
ansi-regex: 6.0.1
dev: false
/tslib/2.4.0:
resolution: {integrity: sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==}
dev: false
/type-fest/1.4.0:
resolution: {integrity: sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==}
engines: {node: '>=10'}
dev: false
/util-deprecate/1.0.2:
resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}
dev: false
/wcwidth/1.0.1:
resolution: {integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==}
dependencies:
defaults: 1.0.3
dev: false
/wrap-ansi/8.0.1:
resolution: {integrity: sha512-QFF+ufAqhoYHvoHdajT/Po7KoXVBPXS2bgjIam5isfWJPfIOnQZ50JtUiVvCv/sjgacf3yRrt2ZKUZ/V4itN4g==}
engines: {node: '>=12'}
dependencies:
ansi-styles: 6.1.0
string-width: 5.1.2
strip-ansi: 7.0.1
dev: false
/ws/8.8.1:
resolution: {integrity: sha512-bGy2JzvzkPowEJV++hF07hAD6niYSr0JzBNo/J29WsB57A2r7Wlc1UFcTR9IzrPvuNVO4B8LGqF8qcpsVOhJCA==}
engines: {node: '>=10.0.0'}
peerDependencies:
bufferutil: ^4.0.1
utf-8-validate: ^5.0.2
peerDependenciesMeta:
bufferutil:
optional: true
utf-8-validate:
optional: true
dev: false

10
received-packages.js Normal file
View File

@ -0,0 +1,10 @@
let lastReceivedAt = new Date();
export let rps = 0;
export let packageCounts = 0;
export const markReceive = () => {
const now = new Date();
rps = (1000 / (now.getTime() - lastReceivedAt.getTime())).toFixed(2);
lastReceivedAt = now;
packageCounts++;
}

37
test-group.js Normal file
View File

@ -0,0 +1,37 @@
import { splitEvery } from 'ramda';
import { parentPort } from 'worker_threads';
import { Client } from './client.js';
const clients = [];
parentPort.on('message', message => {
switch(message.type) {
case 'testOnce':
clients.forEach(worker => {
if (worker.index < message.limit) {
worker.testOnce();
}
});
break;
case 'generateWorkers':
clients.splice(
0,
clients.length,
...new Array(message.end - message.start).fill(undefined).map((_, i) => new Client(i + message.start)),
);
parentPort.postMessage({ type: 'workersGenerated' });
break;
case 'joinRoom':
(async () => {
for (const group of splitEvery(4)(clients)) {
await Promise.all(group.map(async client => {
await client.joinRoom();
parentPort.postMessage({ type: 'oneWorkerJoined', index: client.index });
}));
}
parentPort.postMessage({ type: 'workersJoined' });
})().catch(err => {
parentPort.postMessage({ type: 'joinRoomFailed', error: err });
})
}
});