kopia lustrzana https://github.com/cirospaciari/socketify.py
added more ws bench
rodzic
49cf47c227
commit
b0dede74e4
|
@ -0,0 +1,182 @@
|
|||
const env =
|
||||
"process" in globalThis
|
||||
? process.env
|
||||
: "Deno" in globalThis
|
||||
? Deno.env.toObject()
|
||||
: {};
|
||||
|
||||
const SERVER = env.SERVER || "ws://0.0.0.0:4001";
|
||||
const WebSocket = globalThis.WebSocket || (await import("ws")).WebSocket;
|
||||
const LOG_MESSAGES = env.LOG_MESSAGES === "1";
|
||||
const CLIENTS_TO_WAIT_FOR = parseInt(env.CLIENTS_COUNT || "", 10) || 16;
|
||||
const DELAY = 64;
|
||||
const MESSAGES_TO_SEND = Array.from({ length: 32 }, () => [
|
||||
"Hello World!",
|
||||
"Hello World! 1",
|
||||
"Hello World! 2",
|
||||
"Hello World! 3",
|
||||
"Hello World! 4",
|
||||
"Hello World! 5",
|
||||
"Hello World! 6",
|
||||
"Hello World! 7",
|
||||
"Hello World! 8",
|
||||
"Hello World! 9",
|
||||
"What is the meaning of life?",
|
||||
"where is the bathroom?",
|
||||
"zoo",
|
||||
"kangaroo",
|
||||
"erlang",
|
||||
"elixir",
|
||||
"bun",
|
||||
"mochi",
|
||||
"typescript",
|
||||
"javascript",
|
||||
"Hello World! 7",
|
||||
"Hello World! 8",
|
||||
"Hello World! 9",
|
||||
"What is the meaning of life?",
|
||||
"where is the bathroom?",
|
||||
"zoo",
|
||||
"kangaroo",
|
||||
"erlang",
|
||||
"elixir",
|
||||
"bun",
|
||||
"mochi",
|
||||
"typescript",
|
||||
"javascript",
|
||||
"Hello World! 7",
|
||||
"Hello World! 8",
|
||||
"Hello World! 9",
|
||||
"What is the meaning of life?",
|
||||
"Hello World! 7",
|
||||
"Hello World! 8",
|
||||
"Hello World! 9",
|
||||
"What is the meaning of life?",
|
||||
"where is the bathroom?",
|
||||
"zoo",
|
||||
"kangaroo",
|
||||
"erlang",
|
||||
"elixir",
|
||||
"bun",
|
||||
"mochi",
|
||||
"typescript",
|
||||
"javascript",
|
||||
]).flat();
|
||||
|
||||
const NAMES = Array.from({ length: 50 }, (a, i) => [
|
||||
"Alice" + i,
|
||||
"Bob" + i,
|
||||
"Charlie" + i,
|
||||
"David" + i,
|
||||
"Eve" + i,
|
||||
"Frank" + i,
|
||||
"Grace" + i,
|
||||
"Heidi" + i,
|
||||
"Ivan" + i,
|
||||
"Judy" + i,
|
||||
"Karl" + i,
|
||||
"Linda" + i,
|
||||
"Mike" + i,
|
||||
"Nancy" + i,
|
||||
"Oscar" + i,
|
||||
"Peggy" + i,
|
||||
"Quentin" + i,
|
||||
"Ruth" + i,
|
||||
"Steve" + i,
|
||||
"Trudy" + i,
|
||||
"Ursula" + i,
|
||||
"Victor" + i,
|
||||
"Wendy" + i,
|
||||
"Xavier" + i,
|
||||
"Yvonne" + i,
|
||||
"Zach" + i,
|
||||
])
|
||||
.flat()
|
||||
.slice(0, CLIENTS_TO_WAIT_FOR);
|
||||
|
||||
console.log(`Connecting ${CLIENTS_TO_WAIT_FOR} WebSocket clients...`);
|
||||
console.time(`All ${CLIENTS_TO_WAIT_FOR} clients connected`);
|
||||
|
||||
var remainingClients = CLIENTS_TO_WAIT_FOR;
|
||||
var promises = [];
|
||||
|
||||
const clients = new Array(CLIENTS_TO_WAIT_FOR);
|
||||
for (let i = 0; i < CLIENTS_TO_WAIT_FOR; i++) {
|
||||
clients[i] = new WebSocket(`${SERVER}?name=${NAMES[i]}`);
|
||||
promises.push(
|
||||
new Promise((resolve, reject) => {
|
||||
clients[i].onmessage = (event) => {
|
||||
resolve();
|
||||
};
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
await Promise.all(promises);
|
||||
console.timeEnd(`All ${clients.length} clients connected`);
|
||||
|
||||
var received = 0;
|
||||
var total = 0;
|
||||
var more = false;
|
||||
var remaining;
|
||||
|
||||
for (let i = 0; i < CLIENTS_TO_WAIT_FOR; i++) {
|
||||
clients[i].onmessage = (event) => {
|
||||
if (LOG_MESSAGES) console.log(event.data);
|
||||
received++;
|
||||
remaining--;
|
||||
|
||||
if (remaining === 0) {
|
||||
more = true;
|
||||
remaining = total;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// each message is supposed to be received
|
||||
// by each client
|
||||
// so its an extra loop
|
||||
for (let i = 0; i < CLIENTS_TO_WAIT_FOR; i++) {
|
||||
for (let j = 0; j < MESSAGES_TO_SEND.length; j++) {
|
||||
for (let k = 0; k < CLIENTS_TO_WAIT_FOR; k++) {
|
||||
total++;
|
||||
}
|
||||
}
|
||||
}
|
||||
remaining = total;
|
||||
|
||||
function restart() {
|
||||
for (let i = 0; i < CLIENTS_TO_WAIT_FOR; i++) {
|
||||
for (let j = 0; j < MESSAGES_TO_SEND.length; j++) {
|
||||
clients[i].send(MESSAGES_TO_SEND[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var runs = [];
|
||||
setInterval(() => {
|
||||
const last = received;
|
||||
runs.push(last);
|
||||
received = 0;
|
||||
console.log(
|
||||
last,
|
||||
`messages per second (${CLIENTS_TO_WAIT_FOR} clients x ${MESSAGES_TO_SEND.length} msg, min delay: ${DELAY}ms)`
|
||||
);
|
||||
|
||||
if (runs.length >= 10) {
|
||||
console.log("10 runs");
|
||||
console.log(JSON.stringify(runs, null, 2));
|
||||
if ("process" in globalThis) process.exit(0);
|
||||
runs.length = 0;
|
||||
}
|
||||
}, 1000);
|
||||
var isRestarting = false;
|
||||
setInterval(() => {
|
||||
if (more && !isRestarting) {
|
||||
more = false;
|
||||
isRestarting = true;
|
||||
restart();
|
||||
isRestarting = false;
|
||||
}
|
||||
}, DELAY);
|
||||
restart();
|
|
@ -0,0 +1,53 @@
|
|||
// See ./README.md for instructions on how to run this benchmark.
|
||||
const CLIENTS_TO_WAIT_FOR = parseInt(process.env.CLIENTS_COUNT || "", 10) || 16;
|
||||
var remainingClients = CLIENTS_TO_WAIT_FOR;
|
||||
const COMPRESS = process.env.COMPRESS === "1";
|
||||
const port = process.PORT || 4001;
|
||||
|
||||
const server = Bun.serve({
|
||||
port: port,
|
||||
websocket: {
|
||||
open(ws) {
|
||||
ws.subscribe("room");
|
||||
|
||||
remainingClients--;
|
||||
console.log(`${ws.data.name} connected (${remainingClients} remain)`);
|
||||
|
||||
if (remainingClients === 0) {
|
||||
console.log("All clients connected");
|
||||
setTimeout(() => {
|
||||
console.log('Starting benchmark by sending "ready" message');
|
||||
ws.publishText("room", `ready`);
|
||||
}, 100);
|
||||
}
|
||||
},
|
||||
message(ws, msg) {
|
||||
ws.publishText("room", msg);
|
||||
},
|
||||
close(ws) {
|
||||
remainingClients++;
|
||||
},
|
||||
|
||||
perMessageDeflate: false,
|
||||
},
|
||||
|
||||
fetch(req, server) {
|
||||
if (
|
||||
server.upgrade(req, {
|
||||
data: {
|
||||
name:
|
||||
new URL(req.url).searchParams.get("name") ||
|
||||
"Client #" + (CLIENTS_TO_WAIT_FOR - remainingClients),
|
||||
},
|
||||
})
|
||||
)
|
||||
return;
|
||||
|
||||
return new Response("Error");
|
||||
},
|
||||
});
|
||||
|
||||
console.log(
|
||||
`Waiting for ${remainingClients} clients to connect...\n`,
|
||||
` http://${server.hostname}:${port}/`
|
||||
);
|
|
@ -0,0 +1,51 @@
|
|||
// See ./README.md for instructions on how to run this benchmark.
|
||||
const port = process.env.PORT || 4001;
|
||||
const CLIENTS_TO_WAIT_FOR = parseInt(process.env.CLIENTS_COUNT || "", 10) || 16;
|
||||
|
||||
import { createRequire } from "module";
|
||||
const require = createRequire(import.meta.url);
|
||||
var WebSocketServer = require("ws").Server,
|
||||
config = {
|
||||
host: "0.0.0.0",
|
||||
port,
|
||||
},
|
||||
wss = new WebSocketServer(config, function () {
|
||||
console.log(`Waiting for ${CLIENTS_TO_WAIT_FOR} clients to connect..`);
|
||||
});
|
||||
|
||||
var clients = [];
|
||||
|
||||
wss.on("connection", function (ws, { url }) {
|
||||
const name = new URL(new URL(url, "http://localhost:3000")).searchParams.get(
|
||||
"name"
|
||||
);
|
||||
console.log(
|
||||
`${name} connected (${CLIENTS_TO_WAIT_FOR - clients.length} remain)`
|
||||
);
|
||||
clients.push(ws);
|
||||
|
||||
ws.on("message", function (message) {
|
||||
for (let client of clients) {
|
||||
client.send(message);
|
||||
}
|
||||
});
|
||||
|
||||
// when a connection is closed
|
||||
ws.on("close", function (ws) {
|
||||
clients.splice(clients.indexOf(ws), 1);
|
||||
});
|
||||
|
||||
if (clients.length === CLIENTS_TO_WAIT_FOR) {
|
||||
sendReadyMessage();
|
||||
}
|
||||
});
|
||||
|
||||
function sendReadyMessage() {
|
||||
console.log("All clients connected");
|
||||
setTimeout(() => {
|
||||
console.log("Starting benchmark");
|
||||
for (let client of clients) {
|
||||
client.send(`ready`);
|
||||
}
|
||||
}, 100);
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
import falcon.asgi
|
||||
import falcon.media
|
||||
import asyncio
|
||||
|
||||
clients = set([])
|
||||
remaining_clients = 16
|
||||
|
||||
async def broadcast(message):
|
||||
|
||||
# tasks = [ws.send_text(message) for ws in client]
|
||||
# return await asyncio.wait(tasks, return_when=ALL_COMPLETED)
|
||||
for ws in clients:
|
||||
await ws.send_text(message)
|
||||
# # for ws in clients:
|
||||
# # tasks.append(ws.send_text(message))
|
||||
# await asyncio.wait(tasks, return_when=ALL_COMPLETED)
|
||||
|
||||
|
||||
class SomeResource:
|
||||
|
||||
async def on_get(self, req):
|
||||
pass
|
||||
|
||||
async def on_websocket(self, req, ws):
|
||||
global remaining_clients
|
||||
try:
|
||||
await ws.accept()
|
||||
clients.add(ws)
|
||||
remaining_clients = remaining_clients - 1
|
||||
if remaining_clients == 0:
|
||||
await broadcast("ready")
|
||||
|
||||
while True:
|
||||
payload = await ws.receive_text()
|
||||
await broadcast(payload)
|
||||
|
||||
except falcon.WebSocketDisconnected:
|
||||
clients.remove(ws)
|
||||
remaining_clients = remaining_clients + 1
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
app = falcon.asgi.App()
|
||||
app.add_route('/', SomeResource())
|
||||
# python3 -m gunicorn falcon_server:app -b 127.0.0.1:4001 -w 1 -k uvicorn.workers.UvicornWorker
|
|
@ -0,0 +1,13 @@
|
|||
{
|
||||
"name": "websocket-server",
|
||||
"module": "index.ts",
|
||||
"type": "module",
|
||||
"devDependencies": {
|
||||
"bun-types": "^0.2.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"bufferutil": "^4.0.7",
|
||||
"utf-8-validate": "^5.0.10",
|
||||
"ws": "^8.11.0"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
from socketify import App, AppOptions, OpCode, CompressOptions
|
||||
|
||||
remaining_clients = 16
|
||||
|
||||
def ws_open(ws):
|
||||
ws.subscribe("room")
|
||||
global remaining_clients
|
||||
remaining_clients = remaining_clients - 1
|
||||
if remaining_clients == 0:
|
||||
print("All clients connected")
|
||||
print('Starting benchmark by sending "ready" message')
|
||||
|
||||
ws.publish("room", "ready", OpCode.TEXT)
|
||||
#publish will send to everyone except it self so send to it self too
|
||||
ws.send("ready", OpCode.TEXT)
|
||||
|
||||
|
||||
def ws_message(ws, message, opcode):
|
||||
#publish will send to everyone except it self so send to it self too
|
||||
ws.publish("room", message, opcode)
|
||||
ws.send(message, opcode)
|
||||
|
||||
def ws_close(ws, close, message):
|
||||
global remaining_clients
|
||||
remaining_clients = remaining_clients + 1
|
||||
|
||||
app = App()
|
||||
app.ws("/*", {
|
||||
'compression': CompressOptions.DISABLED,
|
||||
'max_payload_length': 16 * 1024 * 1024,
|
||||
'idle_timeout': 60,
|
||||
'open': ws_open,
|
||||
'message': ws_message,
|
||||
'close': ws_close
|
||||
})
|
||||
app.any("/", lambda res,req: res.end("Nothing to see here!'"))
|
||||
app.listen(4001, lambda config: print("Listening on port http://localhost:%d now\n" % (config.port)))
|
||||
app.run()
|
Plik binarny nie jest wyświetlany.
Po Szerokość: | Wysokość: | Rozmiar: 35 KiB |
File diff suppressed because one or more lines are too long
Po Szerokość: | Wysokość: | Rozmiar: 5.2 KiB |
Ładowanie…
Reference in New Issue