From d42383356ee6922d6f8e0c7cca4dfc48a1eb4ef3 Mon Sep 17 00:00:00 2001 From: Vladimir Dementyev Date: Wed, 18 Aug 2021 00:01:08 +0300 Subject: [PATCH] bench: add k6 example script --- .gitignore | 2 ++ .k6/README.md | 23 ++++++++++++++++++ .k6/chat.js | 66 +++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 91 insertions(+) create mode 100644 .k6/README.md create mode 100644 .k6/chat.js diff --git a/.gitignore b/.gitignore index 777a4ea..358f534 100644 --- a/.gitignore +++ b/.gitignore @@ -31,3 +31,5 @@ /yarn-error.log yarn-debug.log* .yarn-integrity + +.k6/k6 diff --git a/.k6/README.md b/.k6/README.md new file mode 100644 index 0000000..9235bf8 --- /dev/null +++ b/.k6/README.md @@ -0,0 +1,23 @@ +# Benchmarking with k6 + +This folder contains benchmark/stress test scenarios to be used with [k6][]. + +We rely on the [xk6-cable][] extension, so you must first build a custom k6 executable (following the instructions described in the xk6-cable repo) and keep it in the `.k6/` folder. + +## Scenarios + +All scenarios support the following env vars: + +- `CABLE_URL`: WebSocket connection url (defaults to `ws://localhost:8080/cable`). +- `WORKSPACE`: Workspace ID. + +### `chat.js` + +Connect to a chat room, send N (env `NUM` or 5) messages and expect to receive own messages back: + +```sh +./k6 run --vus 20 --duration 10s chat.js +``` + +[k6]: https://k6.io +[xk6-cable]: https://github.com/anycable/xk6-cable diff --git a/.k6/chat.js b/.k6/chat.js new file mode 100644 index 0000000..3fff933 --- /dev/null +++ b/.k6/chat.js @@ -0,0 +1,66 @@ +import { check, sleep, fail } from "k6"; +import cable from "k6/x/cable"; +import { randomIntBetween } from "https://jslib.k6.io/k6-utils/1.1.0/index.js"; + +import { Trend } from "k6/metrics"; + +let rttTrend = new Trend("rtt", true); + +let userId = `100${__VU}`; +let userName = `Kay${userId}`; + +const URL = __ENV.CABLE_URL || "ws://localhost:8080/cable"; +const WORKSPACE = __ENV.WORKSPACE || "demo"; +const MESSAGES_NUM = parseInt(__ENV.NUM || "5"); + +export let options = { + thresholds: { + checks: ["rate>0.9"], + }, +}; + +export default function () { + let client = cable.connect(URL, { + cookies: `uid=${userName}/${userId}`, + }); + + if ( + !check(client, { + "successful connection": (obj) => obj, + }) + ) { + fail("connection failed"); + } + + let channel = client.subscribe("ChatChannel", { id: WORKSPACE }); + + if ( + !check(channel, { + "successful subscription": (obj) => obj, + }) + ) { + fail("failed to subscribe"); + } + + for (let i = 0; i < MESSAGES_NUM; i++) { + let startMessage = Date.now(); + channel.perform("speak", { message: `hello from ${userName}` }); + + let message = channel.receive({ author_id: userId }); + + if ( + !check(message, { + "received its own message": (obj) => obj, + }) + ) { + fail("expected message hasn't been received"); + } + + let endMessage = Date.now(); + rttTrend.add(endMessage - startMessage); + + sleep(randomIntBetween(5, 10) / 10); + } + + client.disconnect(); +}