I love hacking the performance boundaries of the existing browser stacks. In an earlier article, I showed how it was possible to execute a million SQL statements within the browser leveraging Web Workers and WebAssembly.

While this was interesting and certainly demonstrated the sheer power of the browser JavaScript engines, having the browser do stuff in isolation has limited use cases. What would be more useful would be to connect up to a back end so that we can process our SQL on the server. Indeed, this is the foundation for most web applications. I’ve been playing around with Web Sockets for some time now and have been very impressed with the simplicity and performance in the browser.

For this example, I wanted to see how many WebSocket requests I could achieve from a single browser client. To make the test more realistic, I had the server insert a simple record into a Sqlite database on each Web Socket request. As a point of reference, here are the results using straight HTTP from the well respected TechEmpower benchmarks:

This graph lists the top performers for database updates:

My tests are not an apples to apples comparison with this benchmark but I provide it just to give the reader a reference point for a similar use case, that is, doing database updates via the browser.

To run the test, you need a Web Socket Server and a Database engine. I am going to use two of my favourite applications that I immediately install whenever I provision a new hacking environment:

websocketd from here:

and Sqlite from here:

I cannot recommend these applications high enough when you want quick and powerful tools for prototyping or brainstorming ideas.

“Websocketd can turn any program that uses STDIN/STDOUT into a WebSocket server. Like inetd, but for WebSockets.” “SQLite is a self-contained, high-reliability, embedded, full-featured, public-domain, SQL database engine. SQLite is the most used database engine in the world.”

The thing that I love best about these tools, as well as my other favourite hacking tool, PhantomJS is that they are all a self contained executable that will run on any environment, from your cloud based supercomputers to the exquisite RaspberryPi. No installation, dependencies or packaging … just a good old command line executable.

To run the test, create a local directory and copy the websocketd and sqlite executables into that directory. Depending on your environment, you might have to give execute permissions to these files. For my test, I am running on a Windows 10 machine with the following configuration:

Dell XPS

Processor Intel(R) Core(TM) i7–4770 CPU @ 3.40GHz, 3401 Mhz, 4 Core(s), 8 Logical Processor(s) 24 Gigs of RAM

256 SSD Drive

I created a directory called WebSocketTest that looks like this:

Running the server is as simple as executing the following command line:

websocketd --devconsole --port:8081 sqlite3

and you should get something like the following to let you know the server is running:

To make sure that your environment is working, navigate to http://localhost:8081 from your browser. I did my tests on the latest version of Firefox:

Navigating to http://localhost:8081 gives you access to an interactive REPL that allows you to test your environment. In this case, since we are using the Sqlite command shell as our “server”, you can execute any command that you would normally execute using the command line shell:

Basically, what websocketd does is it wraps your command line executable and pipes the stdin and stdout into a Web Socket connection that you can access from the browser. Obviously, this is not what you want to be doing in a production environment but it is great for prototyping ideas. You can try out a few more examples in the devconsole, such as:

.timer on select sqlite_version() as version; create table log(entry); insert into log VALUES(datetime()); select * from log; delete from log;



Make sure you include the trailing ; to terminate your SQL commands!

To give you an idea of just how fast the Sqlite database engine is, lets insert one million records into the log table with this command:

WITH cnt(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM cnt WHERE x<1000000) INSERT INTO log SELECT datetime() FROM cnt;

So it took about

~ 1 second to insert a million rows into the log table

… that is pretty impressive!

Before we go any further, make sure you turn off the Sqlite timer by entering

.timer off

in the REPL! This prevents the client from being swamped by messages from the server on our big update.

Of course, this doesn’t really test our Web Sockets since the above command is send as a single Web Socket to the server, where it is executed. To test how long it would take to send 1 million Web Socket requests, we are going to use the browser console to execute our code directly.

Press F12 to open the developer tools in the browser and from the console, paste the following code:

console.time("Elapsed");

var numMessages=1000000;

var code = "insert into log VALUES(datetime());";

ws.send("BEGIN;")

Array(numMessages).fill(0).forEach(x => {ws.send(code)});

ws.send("COMMIT;")

console.timeEnd("Elapsed");

You should get something that looks like this:

As you can see, on my machine … it took

~4 seconds to send the 1 million requests

to the server and do the SQL inserts!

To verify, close the developer tools (hit F12 again) and re-execute the following command in the REPL:

select count(*) from log;

and you should see that you now have 1,000,000 records in the log table.

Obviously, your results many vary depending on your machine configuration and choice of browser. In any event, you should easily be able to do hundreds of thousands of Web Socket requests per second in a controlled environment.

Since this is only using a single Web Socket connection from a single client, I suspect that we can do millions of requests per second if we leverage multiple clients. My next test will focus on leveraging multiple Web Sockets using Web Workers … so stay tuned.

If you like this article as well as my other articles on Medium, please recommend it!

Thanks.