-
Notifications
You must be signed in to change notification settings - Fork 1.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
variable-looping-vus bugs #1296
Comments
As mentioned in #1331, the second bug related to "wobbling" of VUs is caused by []github.com/loadimpact/k6/lib.ExecutionStep len: 32, cap: 32, [
{TimeOffset: 0, PlannedVUs: 0, MaxUnplannedVUs: 0},
{TimeOffset: 2000000000, PlannedVUs: 1, MaxUnplannedVUs: 0},
{TimeOffset: 3000000000, PlannedVUs: 0, MaxUnplannedVUs: 0},
{TimeOffset: 4000000000, PlannedVUs: 1, MaxUnplannedVUs: 0},
{TimeOffset: 6000000000, PlannedVUs: 2, MaxUnplannedVUs: 0},
{TimeOffset: 7000000000, PlannedVUs: 1, MaxUnplannedVUs: 0},
{TimeOffset: 8000000000, PlannedVUs: 2, MaxUnplannedVUs: 0},
{TimeOffset: 10000000000, PlannedVUs: 3, MaxUnplannedVUs: 0},
{TimeOffset: 11000000000, PlannedVUs: 2, MaxUnplannedVUs: 0},
{TimeOffset: 12000000000, PlannedVUs: 3, MaxUnplannedVUs: 0},
{TimeOffset: 14000000000, PlannedVUs: 4, MaxUnplannedVUs: 0},
{TimeOffset: 15000000000, PlannedVUs: 3, MaxUnplannedVUs: 0},
{TimeOffset: 16000000000, PlannedVUs: 4, MaxUnplannedVUs: 0},
{TimeOffset: 18000000000, PlannedVUs: 5, MaxUnplannedVUs: 0},
{TimeOffset: 19000000000, PlannedVUs: 4, MaxUnplannedVUs: 0},
{TimeOffset: 20000000000, PlannedVUs: 5, MaxUnplannedVUs: 0},
{TimeOffset: 21000000000, PlannedVUs: 4, MaxUnplannedVUs: 0},
{TimeOffset: 22000000000, PlannedVUs: 5, MaxUnplannedVUs: 0},
{TimeOffset: 23000000000, PlannedVUs: 4, MaxUnplannedVUs: 0},
{TimeOffset: 25000000000, PlannedVUs: 3, MaxUnplannedVUs: 0},
{TimeOffset: 26000000000, PlannedVUs: 4, MaxUnplannedVUs: 0},
{TimeOffset: 27000000000, PlannedVUs: 3, MaxUnplannedVUs: 0},
{TimeOffset: 29000000000, PlannedVUs: 2, MaxUnplannedVUs: 0},
{TimeOffset: 30000000000, PlannedVUs: 3, MaxUnplannedVUs: 0},
{TimeOffset: 31000000000, PlannedVUs: 2, MaxUnplannedVUs: 0},
{TimeOffset: 33000000000, PlannedVUs: 1, MaxUnplannedVUs: 0},
{TimeOffset: 34000000000, PlannedVUs: 2, MaxUnplannedVUs: 0},
{TimeOffset: 35000000000, PlannedVUs: 1, MaxUnplannedVUs: 0},
{TimeOffset: 37000000000, PlannedVUs: 0, MaxUnplannedVUs: 0},
{TimeOffset: 38000000000, PlannedVUs: 1, MaxUnplannedVUs: 0},
{TimeOffset: 39000000000, PlannedVUs: 0, MaxUnplannedVUs: 0},
{TimeOffset: 40000000000, PlannedVUs: 0, MaxUnplannedVUs: 0},
] So we should either disregard the "wobbliness" during execution, or preferably ensure such execution plans are not returned. I'm partial to the latter solution, so will look into this next. |
Ah, this may actually be very problematic... 😕 I really hope the solution to this doesn't turn out to be the striping that @mstoykov is currently working on for the |
So, yeah, unfortunately this wobbling seems to be an inherent property of the "more accurate algorithm" I proposed in the second part of #997 (comment). It's true that algorithm gives us a slightly more accurate distribution for small numbers, but it's very inconsistent. See what happens when I incrementally try to distribute 1, 2, 3 and 4 VUs over 4 instances:
See how instance 2 is allotted the single VU in the beginning, but "loses" it when there are 2 VUs (which go to instances 1 and 3). Then instance 3 "loses" that VU when there are 3 VUs in total... The original algorithm (#997 (comment)) seems much more stable in this scenario, but it need to be thoroughly tested, so we can see if that was just a fluke or if it's actually a property of the algorithm:
See how, once an instance has been allotted a VU, it's not "lost" when there are more VUs. If that proves to be universal, we probably should switch to the old algorithm. If not, we should handle the VU increases with the same optimal striping algorithm I proposed for the |
@na-- Unfortunately the original #997 algorithm doesn't seem to fix the wobble. See the tests in #1339, specifically See some failure examples from the
You mean the algorithm used in #1323? Can I reuse parts of that PR for this or would it be a separate implementation? |
😞 Then we probably have to go the harder route... Just to see if this is fixable and we can salvage the easier option, can you try to find some simple example of the
Yes, we can think of the VU increases and decreases in
For example, if you have to ramp up from 0 to 10 VUs over 30 seconds and you want to equally distribute that test run between 3 instances, the algorithm can work somewhat like this:
Of course, the above isn't optimized, we don't need to keep the intermediate result between 2 and 3 in memory, we can filter on the fly. So, a bit more complicated than the current implementation, but not terribly. The mistake here was mine in assuming that the Btw with some refactoring this might even turn out to be simpler than the current implementation, since this would probably also require us to only have a single stream of "events"... So we'd probably need to fix your pet peeve from #1331 (comment) 😅 |
While I was trying to use it for the constant-arrival-rate I came to two conclusions (even without us having to use it for what we currently use ExecutionSegment.Scale):
From the current discussion, we would also need to run the algorithm for all segments, because in the constant arrival rate I first need to split MaxVUs and then based on that to create new segments and a sequence ... so I will first need to run the algorithm for every segment, to get the correct MaxVUs and make segments from that and then a sequence and then to use that ... Given all of that, I propose that in #1323 the ExecutionSegmentSequence calculates the offsets for all segments. This, as shown by benchmarks, should not take much time for easy cases and even for very complicated ones is probably going to be under a second (we can add some info level logging). Also unless we have some pretty strange segment lengths this shouldn't use all that much more memory, especially given that it only happens once. Maybe we can only do it once it is needed but to be honest this will probably be always so ... After that, I propose instead of having ExecutionSegment given as argument everywhere to just give directly Options and then the Executors(and their Configs) can use the ExecutionSegment and ExecutionSegmentSequence to calculate what they want ... Obviously the ExecutionSegmentSequence will get a new
and possibly
|
Hmm I don't like that we have to pass the current Maybe it makes sense that we have a new internal type that encapsulates both the We can construct this new struct after we parse the options (thus, nicely handling any errors, like mismatching segment and sequence). Then we can pass it to the I have no idea how to call that type, but let's use |
Sure, here's the scaling sequence for
Notice that at Here's another more complex example that starts wobbling at
I haven't given much thought on the implementation yet, so I can't comment on your discussion. I'll look into implementing the striped offsets approach, and let you know if I get stuck. :) |
Hmm yeah... Unfortunately we'd have to go with the more complicated approach 😞 I propose the following things:
thoughts? @imiric, until 5. (i.e. #1323) is ready, you should probably look at something else, maybe #1301 or #1283 (comment) |
Noticed a few bugs when manually testing the
variable-looping-vus
(i.e.stages
) executor. The following script can demonstrate both issues:Here's a testrun of that script, first as it is, and then after removing the comment for the
executionSegment
option:Notice how at t=23s (in the cast, ~16s in the first script execution), we start seeing
Start
events for VUs that should have been stopped 😕 We're ramping down at that point, but it seems as if there's a zero-duration sudden jump in VUs... This then repeats a few times until the duration is done 😕The second bug I found happened when I enabled the commented-out execution segment option. Notice the
Graceful stop
event at t=43s (in the cast, ~2s into the second script execution), when we should be ramping up VUs, not stopping them 😕 This then repeats a few times, notice how the value of X in the textcurrently X active looping VUs
wobbles, when it should consistently and gradually increment from 0 to 5 in the first 10 seconds and then gracefully decrement...The text was updated successfully, but these errors were encountered: