k6

A modern load testing tool, using Go and JavaScript

"like unit testing, for performance"

k6 is a modern load testing tool, building on Load Impact's years of experience. It provides a clean, approachable JavaScript scripting API, distributed and cloud execution, and orchestration via a REST API.

Get Started    Guides

JavaScript compatibility mode

New in version 0.26.0

k6 supports running test scripts with different ECMAScript compatibility modes using the run --compatibility-mode CLI option or K6_COMPATIBILITY_MODE environment variable.

Currently two modes are available:

  • base: pure Golang JavaScript VM supporting ES5.1+. Use this mode if your scripts are already written using only ES5.1 features, or were previously transformed by Babel, to reduce startup time, RAM usage and improve performance. See the k6-es6 project for an example Webpack setup that does this transformation outside of k6.
  • extended: transforms scripts to ES5.1 using Babel with ES2015 preset, and loads core.js v2 polyfills. This is the default mode, providing greater JavaScript compatibility, at the expense of startup time, RAM usage and performance.

Base mode example

var http = require("k6/http");
var k6 = require("k6");

module.exports.options = {
  vus: 10,
  duration: "30s",
}

module.exports.default = function() {
  http.get("http://test.loadimpact.com");
  k6.sleep(1);
}

Note that require() is a custom k6 implementation of module loading, which doesn't behave in the same way as the require() call in Node.js. Specifically, it only handles loading of built-in k6 modules, scripts on the local filesystem, and remote scripts over HTTP(S), but it does not support the Node.js module resolution algorithm.

Then run this script with:

k6 run --compatibility-mode=base script.js
K6_COMPATIBILITY_MODE=base k6 run script.js

Here is another more complex example, showing how checks, thresholds and stages are defined and used:

var http = require("k6/http");
var metrics = require("k6/metrics");
var k6 = require("k6");

module.exports.options = {
  stages: [
    { duration: "30s", target: 20 },
    { duration: "1m30s", target: 10 },
    { duration: "20s", target: 0 },
  ],
  thresholds: {
    "failed requests": ["rate<0.1"],
  }
}

var myFailRate = new metrics.Rate("failed requests");

module.exports.default = function() {
  var res = http.get("https://httpbin.test.loadimpact.com/");
  var checkRes = k6.check(res, {
    "status was 200": function(r) { return r.status == 200 }
  });
  if (!checkRes) {
    myFailRate.add(1);
  }
  k6.sleep(1);
}

Performance comparison

There's a substantial difference in performance between both modes, as shown by GNU time below, especially when running tests with a large number of VUs:

/usr/bin/time -v k6 run --compatibility-mode=base \
  --vus 3500 --duration=60s script.js
[...]
User time (seconds): 15.10
System time (seconds): 10.02
Percent of CPU this job got: 40%
Elapsed (wall clock) time (h:mm:ss or m:ss): 1:01.88
Average shared text size (kbytes): 0
Average unshared data size (kbytes): 0
Average stack size (kbytes): 0
Average total size (kbytes): 0
Maximum resident set size (kbytes): 903612
Average resident set size (kbytes): 0
Major (requiring I/O) page faults: 1
Minor (reclaiming a frame) page faults: 352090
Voluntary context switches: 558479
Involuntary context switches: 4689
Swaps: 0
File system inputs: 0
File system outputs: 78856
Socket messages sent: 0
Socket messages received: 0
Signals delivered: 0
Page size (bytes): 4096
Exit status: 0
/usr/bin/time -v k6 run --compatibility-mode=extended \
  --vus 3500 --duration=60s script.js
[...]
User time (seconds): 104.44
System time (seconds): 6.96
Percent of CPU this job got: 101%
Elapsed (wall clock) time (h:mm:ss or m:ss): 1:49.49
Average shared text size (kbytes): 0
Average unshared data size (kbytes): 0
Average stack size (kbytes): 0
Average total size (kbytes): 0
Maximum resident set size (kbytes): 7972316
Average resident set size (kbytes): 0
Major (requiring I/O) page faults: 1
Minor (reclaiming a frame) page faults: 2595676
Voluntary context switches: 535511
Involuntary context switches: 9306
Swaps: 0
File system inputs: 0
File system outputs: 78856
Socket messages sent: 0
Socket messages received: 0
Signals delivered: 0
Page size (bytes): 4096
Exit status: 0

Particularly note the reduction in resident memory usage (7.9GB vs 903MB), CPU usage (101% vs 40%) and total execution time (1m49.49s vs 1m1.88s) when running with "base" mode. The difference in execution time is primarily because of the near-instant VU initialization with "base" mode.

For more performance comparisons, see issue #1167.

Updated 3 months ago

JavaScript compatibility mode


Suggested Edits are limited on API Reference Pages

You can only suggest edits to Markdown body content, but not to the API spec.