feat: 多线程压测。
This commit is contained in:
commit
52bb816282
12
.editorconfig
Normal file
12
.editorconfig
Normal 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
130
.gitignore
vendored
Normal 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.*
|
44
client.js
Normal file
44
client.js
Normal 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
118
index.js
Normal 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
19
logger.js
Normal 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
22
package.json
Normal 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
generated
Normal file
308
pnpm-lock.yaml
generated
Normal 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
10
received-packages.js
Normal 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
37
test-group.js
Normal 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 });
|
||||
})
|
||||
}
|
||||
});
|
Loading…
Reference in New Issue
Block a user