0

So I have a bit of a question, that relates both to k6 and to I guess JavaScript itself. (Also I realize k6 is built upon Go language but uses JS).

Anyways in K6 you have a default function that looks like this:

export default function () {
  http.get('https://test.k6.io');
  sleep(1);
}

In my scenario I need to wait 400ms between two different HTTP requests. K6 has an experimental setTimeout function that does this. So I simply did the below:

export default () => {
http.patch(firstURL,body,params)
setTimeout(() => {
  const res = http.post(secondURL,body,params)
  console.log(res.status)
}, "400");
}

So this did indeed work. It appeared to wait 400ms before executing the second request. However my question is: While it's waiting for that 400ms to end, does the main default function "end"?

As in will it move to the next iteration while that 400ms is finishing up, or will the default function wait for everything to finish before it finally finishes itself? Apologies if the question is confusing, not sure of a better way to explain it.

My initial guess is that the execution stalls until the second request finishes anyways?

isherwood
  • 58,414
  • 16
  • 114
  • 157
msmith1114
  • 2,717
  • 3
  • 33
  • 84
  • 1
    Minor: `"400"` should be `400`. Related: https://stackoverflow.com/questions/38176083/settimeout-blocks-eventloop – jarmod May 15 '23 at 16:57
  • No, the default-exported function does not wait for the `setTimeout` callback to occur. It returns immediately after scheduling the timer, just like `setTimeout` itself returns immediately. `setTimeout` is not a `sleep` - you should rather compare it to a started goroutine that finishes on its own. – Bergi May 15 '23 at 17:15
  • Is this question about `setTimeout` or how to write this with k6? With k6, you'd simply do `http.get(firstRequest); sleep(0.4); http.get(secondRequest);` – both `sleep` and `http.get` are synchronous – knittl May 15 '23 at 17:49
  • @knittl I would've done that but I believe the sleep function only works in seconds (according to their documentation). – msmith1114 May 16 '23 at 12:07
  • @msmith1114 you can use fractional seconds `sleep(0.1)` sleeps for 100 ms. I have used that successfully in my own projects – knittl May 16 '23 at 12:57
  • @knittl Well dang....wish I realized that, that makes things WAY simpler lol – msmith1114 May 16 '23 at 13:22
  • 1
    Voting to reopen: this question has a k6-specific answer that differs from the way one would implement this with pure JavaScript – knittl May 16 '23 at 15:18
  • @knittl Agreed, since the k6 docs also don't specifically state you can do this either. – msmith1114 May 16 '23 at 15:31
  • @Bergi this question was closed by you. Would you reconsider, given that k6 works differently from vanilla JavaScript? – knittl May 16 '23 at 15:55
  • @knittl I did not realise that k6 had its own JS environment (or even dialect), I thought the first snippet was Go code (which, in hindsight, it obviously is not). Does its execution model (event loop etc) differ from that of a browser as well? Then sure, go ahead and write your answer :-) – Bergi May 16 '23 at 16:01
  • @Bergi thanks! Up until a few versions ago, there wasn't even an event loop, everything was asynchronous. k6 (more exactly goja, the JS runtime written in Go) is now gaining the ability to run asynchronous code – knittl May 16 '23 at 18:26

1 Answers1

1

Frame challenge ahead.

sleep in k6 is a synchronous call and blocks execution, there is (currently) no need to use asynchronous methods to do the same.

The documentation states that it takes the "duration, in seconds", but fails to explicitly mention that fractional seconds are supported as well. There are two hints on the page though:

  1. It specifies the parameter type as "number" (not "integer", mind you).
  2. The first example sleeps a random amount: sleep(Math.random() * 30). Math.random() returns a floating point number between 0 and 1, thus the duration of the sleep method will also be a floating point number.

Don't believe me? This is easy to verify:

import { sleep } from 'k6';
export default function() {
    console.log(new Date());
    sleep(0.1);
    console.log(new Date());
}

Output:

INFO[0002] "2023-05-16T16:25:18.085Z"                    source=console
INFO[0002] "2023-05-16T16:25:18.187Z"                    source=console

Which gives roughly 100 ms (i.e. 0.1 seconds) between the two log calls.

knittl
  • 246,190
  • 53
  • 318
  • 364