Logo
Back to perspectives
September 01, 2022Release announcements 4 min

Load Testing with mediasoup

By David DiMaria

Want to find out exactly how much your your SFU can handle? We’ve built an open source load test server that solves the limitations of SFU testing with headless browsers, so you can test over 1,000 connections per load test server. Take a look at this overview for more details — and if you’re ready to put it to use, read on.

Arcas load testing depends on GStreamer version `1.18.X` being installed on your computer. If you do not have GStreamer installed you can use the following links to download:

NOTE: At this time only GStreamer versions `1.18.X` are compatible with this demo.

MacOS will need to install both of the following:  

After installing both of those packages, please run the following commands in the terminal:

mkdir -p /usr/local/opt/gst-plugins-base
ln -s /Library/Frameworks/GStreamer.framework/Versions/1.0/lib /usr/local/opt/gst-plugins-base/lib
mkdir -p /usr/local/opt/gstreamer ln -s /Library/Frameworks/GStreamer.framework/Versions/1.0/lib /usr/local/opt/gstreamer/lib

To get a mediasoup SFU up and running quickly, let's pull down some skeleton code from https://github.com/arcas-io/arcas-load-test-mediasoup-example.

git clone -b skeleton https://github.com/arcas-io/arcas-load-test-mediasoup-example.git cd arcas-load-test-mediasoup-example/src

Let's start by creating an entry file:

touch index.js

Using your favorite editor, import the SDK and mediasoup signaling code:

import { Session } from "@arcas/sdk";
import { deviceLoaded, createProducerTransport } from "./signaling.js";

Now let's define some test defaults:

const LOAD_TEST_COUNT = 100;
const TEST_SOAK_TIME_S = 10;
const SOCKET_URI = "https://127.0.0.1:3000";
const SERVERS = ["[::1]:50051"];

The `LOAD_TEST_COUNT` is the number of producers we want to create that will send video to the mediasoup SFU. The `TEST_SOAK_TIME_S` is the number of seconds to keep the test running. The `SOCKET_URI` value is set in the `server/package.json` file in the `start` script. The `SERVERS` value is set in the `package.json` file in the `server` script. In future posts, I'll show you how to scale the Arcas Load Test servers to increase the load test capacity.

In this test, we're configuring it to create 100 producers (peer connections) that will produce video in the Arcas Load Test server for a total of 10 seconds. Feel free to modify to test how much load the SFU can accommodate.

Using the `Session` class in the SDK, create the session:

const session = await Session.create({
	name: "First Session",
	servers: SERVERS,
	protoPath: "/proto/webrtc.proto",
	logLevel: "NONE",
	pollingStateS: 1,
});

We're giving the session a name: `First Session`. This will come in handy in later posts about using the Arcas Portal. The other important session variable is `pollingStateS`. This tells the Arcas Load Test server to poll the internals for stats every `1` second. You may want to increase this if scaling the Arcas Load Test servers.

We can now start the session to let the server know we're ready to start sending some load:

await session.start();

The next step is to wait for the device to load before engaging the producers. The remaining code creates `LOAD_TEST_COUNT` producer transports and holds the test for `TEST_SOAK_TIME_S` seconds.

await deviceLoaded(SOCKET_URI, async (device) => {
	const TEST_INTERVAL_S = 1;
	let TEST_COUNTER_S = 0;
	
	// create LOAD_TEST_COUNT producer transports
	for (let i = 0; i < LOAD_TEST_COUNT; i++) {
	await createProducerTransport(device);
}

const interval = setInterval(async () => {
	TEST_COUNTER_S += TEST_INTERVAL_S;
	
	const stats = await session.getStats();
	const num_sending = stats.session.peer_connection_state.num_sending;
	const elapsed_time = stats.session.elapsed_time;
	console.log(
		`num_sending: ${num_sending}, elapsed_time: ${elapsed_time} seconds`
	);
		
	if (TEST_COUNTER_S >= TEST_SOAK_TIME_S) {
		clearInterval(interval);
		await session.stop();
		process.exit();
		}
	}, TEST_INTERVAL_S * 1000);
});

That's all the code you'll need to write for this test.The next step is to install and start the mediasoup SFU. Before we install the server, ensure that you meet the requirements:

To install the server:

cd server && yarn

The installation may take several minutes downloading and compiling the mediasoup source code.

Once that's done, start the mediasoup SFU:

yarn start

You should see the output:

> mediasoup-server@0.1.2 start /arcas-load-test-mediasoup-example/server
> PORT=3000 WS_HOST=127.0.0.1 SERVER_HOST=0.0.0.0 node index.js

server is running on 127.0.0.1:3000/ws
creating mediasoup worker
mediasoup router created in worker

In a separate terminal window in the `/arcas-load-test-mediasoup-example` directory, start the Arcas Load Test server:

yarn && yarn server

Note: If this produces an error loading gst-plugins-base, make sure your GStreamer version is 1.18.x and that you have followed the installation instructions above.

With both the mediasoup SFU and the Arcas Load Test server running, we can now start the test. In a separate terminal window in the `/arcas-load-test-mediasoup-example` directory, kick off the test:

yarn start

You should see the test output:

num_sending: 100, elapsed_time: 1
num_sending: 100, elapsed_time: 2
num_sending: 100, elapsed_time: 3
num_sending: 100, elapsed_time: 4
num_sending: 100, elapsed_time: 5
num_sending: 100, elapsed_time: 6
num_sending: 100, elapsed_time: 7
num_sending: 100, elapsed_time: 8
num_sending: 100, elapsed_time: 9
num_sending: 100, elapsed_time: 10
✨ Done in 10.96s.

Note: The first `num_sending` may be less than 100 as the service ramps up.

You can now stop the mediasoup SFU and the Arcas Load Test server if you don't plan to run further tests.

That was easy, right? We wrote some code to engage signaling of the mediasoup SFU and started and created a session in the Arcas Load Test server. We then created producer peer connections that actually send video streams on the Arcas Load Test server.

In future posts, I'll detail how to monitor the SFU during the test. Until then, happy testing!

David DiMaria
David DiMariaHead of Engineering, Little Bear Labs

David is a 20+ year engineering veteran and open source advocate. He loves writing, teaching, and talking about Rust and OSS.


More perspectives