I would like to model my workload as realistic as possible, but see nothing in the documentation about constructs as looping and things as markov chains (Percentage -> Scenario).
It should be possible to do this with plain JavaScript, but I'm a bit suprised that there are no example and nobody is asking about this.
Am I missing something?
Thanks!
Really interested in what use case you have for modeling workload with a markov process? Basically it's a matrix of states with transitional probabilities so simple to implement but why? What use case would need statistical modeling of probable outcomes (paths really but still)?
I am not debunking the idea, I am just curious and would like to see some use cases for this since I have only seen it used in statistical functional quality models.
@micsjo Indeed, I want to use it to model navigation paths in my scenarios. Basically just to create a switch between groups based on percentage:
50% Catalog page
30% Checkout page
20% Account page
Simple to create, but it would be nice if there was a more generic API to do this. This could be an extension on the group feature?
I don't think this is very suitable for implementing in k6 itself. I'm not very familiar with markov chains and how other tools implement them, but having a simple graph of pages and probabilities between them and traversing that with a simple JS function seems relatively painless and simple. Something like this:
import http from 'k6/http';
let pageGraph = {
home: {
method: "GET",
url: "https://test.loadimpact.com",
next: [
{ prob: 0.4, id: "contacts" },
{ prob: 0.5, id: "news" },
// 10% chance of stop
],
},
contacts: {
method: "GET",
url: "https://test.loadimpact.com/contacts.php",
next: [
{ prob: 0.8, id: "home" },
// 20% chance of stop
],
},
news: {
method: "GET",
url: "https://test.loadimpact.com/news.php",
next: [
{ prob: 0.3, id: "home" },
{ prob: 0.3, id: "contacts" },
// 40% chance of stop
],
},
};
function traverse(pageId, level) {
let page = pageGraph[pageId];
console.log(`VU ${__VU}, ITER ${__ITER}, level ${level}:\t Traversing ${pageId} (${page.method} ${page.url})`)
http.request(page.method, page.url);
// Do other stuff if something more complicated is required...
let acum = 0, rand = Math.random();
for (let i = 0; i < page.next.length; i++) {
acum += page.next[i].prob;
if (acum > rand) {
// Recursion probably isn't the best way to handle that, but works for a simple example...
return traverse(page.next[i].id, level + 1);
}
}
}
export default function () {
traverse("home", 0);
};
It can be extended and improved in a lot of ways, of course. That's the main reason I don't think it's a good idea to include it in k6 itself - it isn't something essential to the core functionality of a load-testing tool and it can be easily and more flexibly implemented outside of it. For example, in the above example, I can easily add an http.batch() call in some of those pages, or use group() calls, or any other action via a callback function, but I can't do things like that if we bake some sort of markov chain API in k6 itself. While you can always make something like the above code into a JS library and reuse it across all of your k6 scripts without issues...
Closing this for now, but feel free to reopen if you disagree with my assessment and think that there are good reasons to add something like this in k6.
@na-- Thank you for the ellaborate answer! I agree that it should not end up in the k6 core. It would be nice if features like this would be available in a add-on library for k6. For now I will write my own.
Most helpful comment
I don't think this is very suitable for implementing in k6 itself. I'm not very familiar with markov chains and how other tools implement them, but having a simple graph of pages and probabilities between them and traversing that with a simple JS function seems relatively painless and simple. Something like this:
It can be extended and improved in a lot of ways, of course. That's the main reason I don't think it's a good idea to include it in k6 itself - it isn't something essential to the core functionality of a load-testing tool and it can be easily and more flexibly implemented outside of it. For example, in the above example, I can easily add an
http.batch()call in some of those pages, or usegroup()calls, or any other action via a callback function, but I can't do things like that if we bake some sort of markov chain API in k6 itself. While you can always make something like the above code into a JS library and reuse it across all of your k6 scripts without issues...Closing this for now, but feel free to reopen if you disagree with my assessment and think that there are good reasons to add something like this in k6.