Hi
I have a requirement to use specific IDs for specific scenarios, and each iteration of each scenario must use a different ID.
This is the approach I’ve taken: Define the scenarios, then create a SharedArray
of objects that have a list of IDs for each scenario. In the example below I’ve simplified reality for the sake of analysis by generating a list of integers (in reality these are loaded from a file).
I have two questions:
- Why is it so slow to access an array?
- What alternatives are there that are faster?
Thanks in advance for taking the time to help
const testCaseScenarios = {
Valid_Login: {
exec: 'doValidLogin',
executor: 'shared-iterations',
iterations: 2500,
vus: 25,
maxDuration: '1h',
},
Invalid_Login: {
exec: 'doInvalidLogin',
executor: 'shared-iterations',
iterations: 2500,
vus: 25,
maxDuration: '1h',
},
}
export const options = {
scenarios: testCaseScenarios,
};
let idList = new SharedArray('idList', function () {
return [
{ scenarioName: 'Valid_Login', ids: makeArrayOfInt(1, testCaseScenarios.Valid_Login.iterations) },
{ scenarioName: 'Invalid_Login', ids: makeArrayOfInt(testCaseScenarios.Valid_Login.iterations+1, testCaseScenarios.Invalid_Login.iterations) },
]
})
function makeArrayOfInt(start, count) {
const numbers = [];
for (let i = 0; i < count; i++) {
numbers.push(start + i)
}
return numbers
}
The issue may lie with the approach I’ve chosen, or how I’m accessing the idList
for each test to get the id - see getMyId()
:
export function doValidLogin() {
login()
}
export function doInvalidLogin() {
login()
}
function login() {
const id = getMyId()
// Remainder of method removed to focus on the one function above
}
function getMyId() {
const scenarioDefinition = idList.filter(x => x.scenarioName === scenario.name)
if (!scenarioDefinition || scenarioDefinition.length < 1) {
throw new Error(`No definition in idList with scenarioName '${scenario.name}'`)
}
const id = scenarioDefinition[0].ids[scenario.iterationInInstance]
if (!id) {
throw new Error(`No id in the ids of idList with scenarioName '${scenario.name}' at position ${scenario.iterationInInstance}.\nidList: ${JSON.stringify(scenarioDefinition[0].ids)}`)
}
return id
}
When I run this locally, I see the 5000 http requests completing, but they take ages
running (0h00m17.9s), 00/50 VUs, 5000 complete and 0 interrupted iterations
Invalid_Login ✓ [======================================] 25 VUs 0h00m17.9s/1h0m0s 2500/2500 shared iters
Valid_Login ✓ [======================================] 25 VUs 0h00m17.9s/1h0m0s 2500/2500 shared iters
iteration_duration...: avg=176.22ms min=9.99ms med=36ms max=2.62s p(90)=545.47ms p(95)=803.62ms
iterations...........: 5000 279.016878/s
If I replace the getMyId()
function with a simple return 1
, the test is instantaneous:
running (0h00m00.0s), 00/50 VUs, 5000 complete and 0 interrupted iterations
Invalid_Login ✓ [======================================] 25 VUs 0h00m00.0s/1h0m0s 2500/2500 shared iters
Valid_Login ✓ [======================================] 25 VUs 0h00m00.0s/1h0m0s 2500/2500 shared iters
iteration_duration...: avg=2.19µs min=0s med=0s max=1ms p(90)=0s p(95)=0s
iterations...........: 5000 499995.00005/s
The complete script for anyone who wants to try run this locally:
import { SharedArray } from 'k6/data';
import { scenario } from 'k6/execution';
const testCaseScenarios = {
Valid_Login: {
exec: 'doValidLogin',
executor: 'shared-iterations',
iterations: 2500,
vus: 25,
maxDuration: '1h',
},
Invalid_Login: {
exec: 'doInvalidLogin',
executor: 'shared-iterations',
iterations: 2500,
vus: 25,
maxDuration: '1h',
},
}
export const options = {
scenarios: testCaseScenarios,
};
let idList = new SharedArray('idList', function () {
return [
{ scenarioName: 'Valid_Login', ids: makeArrayOfInt(1, testCaseScenarios.Valid_Login.iterations) },
{ scenarioName: 'Invalid_Login', ids: makeArrayOfInt(testCaseScenarios.Valid_Login.iterations+1, testCaseScenarios.Invalid_Login.iterations) },
]
})
function makeArrayOfInt(start, count) {
const numbers = [];
for (let i = 0; i < count; i++) {
numbers.push(start + i)
}
return numbers
}
export function doValidLogin() {
login()
}
export function doInvalidLogin() {
login()
}
function login() {
const id = getMyId()
}
function getMyId() {
// return 1
const scenarioDefinition = idList.filter(x => x.scenarioName === scenario.name)
if (!scenarioDefinition || scenarioDefinition.length < 1) {
throw new Error(`No definition in idList with scenarioName '${scenario.name}'`)
}
const id = scenarioDefinition[0].ids[scenario.iterationInInstance]
if (!id) {
throw new Error(`No id in the ids of idList with scenarioName '${scenario.name}' at position ${scenario.iterationInInstance}.\nidList: ${JSON.stringify(scenarioDefinition[0].ids)}`)
}
return id
}