DEV Community

loading...
Cover image for Load Test with Javascript

Load Test with Javascript

chseki profile image Christian Seki ・4 min read

Javascript is everywhere!

Maybe you're not surprised to know that JS enables us to build nearly any sort of application for any platform.

But what I never heard before is the useability to write Javascript Code to execute load and performance testing, and even better collect metrics from these tests to understand the application behavior.

Tell me more...

The tool that has given us this kind of power is 🔧K6🔧.

But what is this exactly? From k6 official site:

k6 is a developer-centric, free, and open-source load testing tool built for making performance testing a productive and enjoyable experience.

k6 is written in Go but exposes a Javascript API allowing us to write javascript code to interact with.

Installation 💾

  • There's a lot of ways to get the k6 binary, go ahead into their official guide and get one of them.

  • You can also follow this guide to run your first load test even in a local environment.

Nodejs vs Golang

Let's use k6 to compare the performance from a simple API written in Golang and the other one in Nodejs.

  • The Node app uses the well known expressjs framework ➡️ app.js
  • The Go app uses the iris framework ➡️ main.go

Just to Make it quite clear, the App will consume considerable CPU resources being a disadvantage to Nodejs API 😬

Both apps will calculate the nth value of Fibonacci sequence passed as path param, e.g apiUrl/fibonacci/7 must return:

{
  "fibonacci": 34   
}
Enter fullscreen mode Exit fullscreen mode

There's a health check endpoint either: apiUrl/hc I encourage you to call this endpoint manually during the second minute of the load test.

Test Scenario 📋

We're testing just an API endpoint in isolation to see how the endpoint performance trends over time. The scenario is as follow:

  1. In the first minute of the test the system will ramp up until achieving 100 virtual users.
  2. Each virtual user will make an HTTP Request to the endpoint: apiUrl/fibonacci/9999999 every 100ms.
  3. Holding the step 2 for two minutes.
  4. The last minute will ramp down virtual users to 0.
  • k6 will take 4 minutes to run the test described above.
  • The test have a simple goal, declared in options object: http_req_duration: ['p(95)<1000'] which means, 95% of the requests made must take less than 1 second.

k6-test.js

import http from 'k6/http';
import { sleep } from 'k6';

const SLEEP_DURATION = 0.1;

export let options = {
    stages: [
        { duration: "1m", target: 100 },
        { duration: "2m", target: 100 },
        { duration: "1m", target: 0 }
    ],
    thresholds: {
        http_req_duration: ['p(95)<1000'] // 99% request must complete below 1s
    }
}

const BASE_URL = __ENV.API_BASE === "GOLANG" ? "http://localhost:8080" : "http://localhost:9090" 
const HEADERS = { "Content-Type": "application/json" }

export default () => {
    http.get(`${BASE_URL}/fibonacci/9999999`);
    sleep(SLEEP_DURATION);
}
Enter fullscreen mode Exit fullscreen mode

Running the load test with k6 💪

1.Clone the 📜example code📜 and execute docker-compose up. Both apps will expose these endpoints:

App Endpoints Port
Golang /hc /fibonacci/n 8080
Nodejs /hc /fibonacci/n 9090

2.You can run both tests in parallel opening two terminals or one at time, it's up to you.

  • To run the Golang load test in the root project folder, execute: k6 run ./k6-test.js -e API_BASE=GOLANG
  • And to run the Nodejs load test: k6 run ./k6-test.js

I know that it's a really simple test but I like to keep that phrase in mind:

Simple testing is better than no testing

Show me the winner

k6 output for Nodejs app

Alt Text

k6 output for Golang app

Alt Text

  • You can call the health check endpoint of both apps during the load test to check the response time.

1.The HTTP Request to Nodejs takes on average 15s and the Golang app 237ms.
2.Due to this HTTP request duration, in the same amount of time Golang handles 52103 more requests than Nodejs.


Golang won, but how ? 🤔

Analyzing containers resource usage statistics during the tests, you can see the Golang container uses more than one CPU to handle the requests while Nodejs uses just one CPU.

docker stats
Alt Text

Another important point is that Golang uses a separate goroutine per HTTP request handling the requests in a concurrency way.

Conclusion

In case that you have executed both tests will figure out that Go surpasses NodeJS in this scenario. But why?
Both apps have one main task which is to calculate the nth sequence of a Fibonacci number, and depending on the nth number the task can consuming considerable CPU resources, and Nodejs is not designed for that.
Therefore using k6, you'll be able to catch performance regression and problems earlier. You can also write stress tests to check whether the application gradually scale up its infrastructure, allowing you to build resilient systems and robust applications.

Discussion (8)

pic
Editor guide
Collapse
crimsonmed profile image
Médéric Burlet

but by default goland uses multiple cores on your CPU where as node uses one. wouldn't it be more fair to run a pm2 cluster for node to utilize also multiple cores?

Collapse
0x12b profile image
Simon Aronsson

There are multiple optimizations that may be done in go as well to make it even more performant. To me, the point of the article is not to crown one language superior, so "fairness" really is beside the point, but I might be wrong.

All it says is that if you want to do CPU-bound work and split the workload across multiple threads/cores, then go will definitely be the better choice as you get really powerful concurrency primitives provided out of the box.

Collapse
crimsonmed profile image
Médéric Burlet

I think would have been interesting to see also how node handles loads if using multiple cores too as who knows it might be even more performant.

Collapse
chseki profile image
Collapse
devtalhaakbar profile image
Muhammad Talha Akbar

Thanks for sharing. I have never stress-tested APIs or servers before however, if I do, I'll definitely look into k6. It does seem like a no-hassle tool to get you started.

Collapse
gillarp profile image
sopwerDev

K6 seems new for me, thanks for this info.

Collapse
cdavid15 profile image
Craig Davidson

Big fan of K6. Very simple and easy to use and nice looking dashboards very straight forward using grafana.

Collapse
chseki profile image
Christian Seki Author

Good point about grafana dashboard I'll definitely try it.