As reported by @sniku, browser instances are created and destroyed on each iteration, and there's currently no way of running multiple iterations that use the same instance. This is important if we want to reduce the overhead of starting and stopping processes after each iteration.
The script expected to work:
script.js
```js
import { sleep } from 'k6';
import { chromium } from 'k6/x/browser';
export let options = {
iterations: 3
}
// cache for the browser object
let browser = null;
export default function () {
// create the browser object only on the first iteration and then reuse it
console.log(`==== ITER ${__ITER} ====`)
browser = browser || chromium.launch({
headless: false
});
let context = browser.newContext();
let page = context.newPage();
page.goto('https://test.k6.io/', { waitUntil: 'networkidle' });
sleep(3);
}
```
Proposed solution
The main reason this doesn't work is because our main browser context is based on the VU context we receive from k6:
So the solution should be to stop depending on the VU context, but since this is the only way for extensions to know when k6 itself is shutting down, we probably need for k6 to provide a better way to handle this. Also see https://github.com/grafana/k6/issues/2432.
It might make sense to have at least 2 contexts in k6 that extensions have access to:
the VU-iteration context, whose lifetime is for the duration of an iteration. This is what we have now.
the test context, whose lifetime is for the duration of the test run. We can then use this as a signal to shutdown the browser, remove the data directory, etc.
@grafana/k6-browser, we might want to tackle this next. So, we can replicate the remote behavior locally, too. We can get more feedback from OSS users.
As reported by @sniku, browser instances are created and destroyed on each iteration, and there's currently no way of running multiple iterations that use the same instance. This is important if we want to reduce the overhead of starting and stopping processes after each iteration.
The script expected to work:
script.js
```js import { sleep } from 'k6'; import { chromium } from 'k6/x/browser'; export let options = { iterations: 3 } // cache for the browser object let browser = null; export default function () { // create the browser object only on the first iteration and then reuse it console.log(`==== ITER ${__ITER} ====`) browser = browser || chromium.launch({ headless: false }); let context = browser.newContext(); let page = context.newPage(); page.goto('https://test.k6.io/', { waitUntil: 'networkidle' }); sleep(3); } ```Proposed solution
The main reason this doesn't work is because our main browser context is based on the VU context we receive from k6:
https://github.com/grafana/xk6-browser/blob/111414477bd66453177f273118b207bf44e0db5d/chromium/browser_type.go#L112-L117
The browser process is also started using a descendant context.
Since the VU context is cancelled after each iteration, all of these dependent processes will be cancelled as well. The process itself will be
SIGKILL
ed.So the solution should be to stop depending on the VU context, but since this is the only way for extensions to know when k6 itself is shutting down, we probably need for k6 to provide a better way to handle this. Also see https://github.com/grafana/k6/issues/2432.
It might make sense to have at least 2 contexts in k6 that extensions have access to:
Or, we could instead go with an event-based system as proposed in https://github.com/grafana/k6/issues/2432#issuecomment-1065218518. This should be discussed and agreed with the k6 core team.