Search code examples
javascriptbenchmarkingk6

How can I run multiple functions in k6 simultaneously, with specified rate per function


I'm trying to figure out a way to issue two separate requests in k6, with each request limited in relation to the other.

For example, I have two POST requests created, I want one to be hit 90% of the test run and the other 10%, to simulate a more busy and less busy endpoints being hit by requests on the same HTTP server.

EDIT: The point of the exercise is not to generate a predictable load, but to generate a maximum (in terms of ops/sec) load the server can take and measure it. The different rates of request types are needed for the benchmark to simulate a realistic load.


Solution

  • Use scenarios to call different test functions with different request rates by specifying a constant arrival rate executor.

    You have to pre-calculate the per-endpoint rates manually, but you could easily define a function to compute the correct rates from a total base rate.

    const TOTAL_RPS = 100;
    function rate(percentage) {
      return TOTAL_RPS * percentage;
    }
    
    export const options = {
      scenarios: {
        busy: {
          exec: 'busy_endpoint',
          executor: 'constant-arrival-rate',
          duration: '10m',
          preAllocatedVUs: 50,
          rate: rate(0.9) // 90%
        },
        lazy: {
          exec: 'less_busy_endpoint',
          executor: 'constant-arrival-rate',
          duration: '10m',
          preAllocatedVUs: 5,
          rate: rate(0.1), // // 10%
        }
      }
    };
    
    export function busy_endpoint() {
      // will be called 90 times per second (90% of 100 rps)
      http.get('http://example.com');
    }
    
    export function less_busy_endpoint() {
      // will be called 10 times per second (10% of 100 rps)
      http.get('http://example.com');
    }
    

    Depending on your requirements and the complexity of the logic, an alternative could be a stochastic approach: each time you enter the method, you generate a random number and based on the result take one or the other endpoint (or any logic for that matter).

    What could that look like?

    function busy_endpoint() {
      // will be called roughly for 90% of your requests
      http.get('http://example.com');
    }
    
    function less_busy_endpoint() {
      // will be called roughly for 10% of your requests
      http.get('http://example.com');
    }
    
    function get_endpoint() {
      const r = Math.random();
      if (r < 0.1) return less_busy_endpoint;
      return busy_endpoint;
    }
    
    export default function() {
      const endpoint = get_endpoint(); // gets busy with 90% chance and less_busy with 10% chance
      endpoint(); // calls the endpoint
    }