Skip to content

Commit

Permalink
WIP jumps in variable looping VUs
Browse files Browse the repository at this point in the history
This needs jumpy stages in order to see actual difference as goTo isn't
used all that much. To be honest the improvement seems way too big to me,
but I guess in this particular big numerator situation it's worht it.

name                                                                                                              old time/op    new time/op    delta
VariableLoopingVUsGetRawExecutionSteps/seq:;segment:/normal-8                                                        357µs ± 1%     356µs ± 1%     ~     (p=0.690 n=5+5)
VariableLoopingVUsGetRawExecutionSteps/seq:;segment:/jumpy-8                                                        1.86ms ± 1%    1.84ms ± 1%     ~     (p=0.151 n=5+5)
VariableLoopingVUsGetRawExecutionSteps/seq:;segment:/rollercoaster-8                                                3.49ms ± 6%    3.45ms ± 2%     ~     (p=1.000 n=5+5)
VariableLoopingVUsGetRawExecutionSteps/seq:;segment:0:1/normal-8                                                     358µs ± 2%     354µs ± 2%     ~     (p=0.310 n=5+5)
VariableLoopingVUsGetRawExecutionSteps/seq:;segment:0:1/jumpy-8                                                     1.87ms ± 2%    1.85ms ± 1%     ~     (p=0.095 n=5+5)
VariableLoopingVUsGetRawExecutionSteps/seq:;segment:0:1/rollercoaster-8                                             3.45ms ± 1%    3.49ms ± 3%     ~     (p=0.222 n=5+5)
VariableLoopingVUsGetRawExecutionSteps/seq:0,0.3,0.5,0.6,0.7,0.8,0.9,1;segment:0:0.3/normal-8                        102µs ± 1%     103µs ± 1%   +1.03%  (p=0.032 n=5+5)
VariableLoopingVUsGetRawExecutionSteps/seq:0,0.3,0.5,0.6,0.7,0.8,0.9,1;segment:0:0.3/jumpy-8                         569µs ± 1%     568µs ± 1%     ~     (p=0.841 n=5+5)
VariableLoopingVUsGetRawExecutionSteps/seq:0,0.3,0.5,0.6,0.7,0.8,0.9,1;segment:0:0.3/rollercoaster-8                1.24ms ± 3%    1.23ms ± 1%     ~     (p=0.548 n=5+5)
VariableLoopingVUsGetRawExecutionSteps/seq:0,0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1;segment:0:0.1/normal-8           35.1µs ± 1%    35.3µs ± 1%     ~     (p=0.421 n=5+5)
VariableLoopingVUsGetRawExecutionSteps/seq:0,0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1;segment:0:0.1/jumpy-8             182µs ± 1%     179µs ± 2%   -1.64%  (p=0.032 n=5+5)
VariableLoopingVUsGetRawExecutionSteps/seq:0,0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1;segment:0:0.1/rollercoaster-8     384µs ± 2%     380µs ± 1%     ~     (p=0.310 n=5+5)
VariableLoopingVUsGetRawExecutionSteps/seq:;segment:2/5:4/5/normal-8                                                 135µs ± 2%     136µs ± 1%     ~     (p=0.548 n=5+5)
VariableLoopingVUsGetRawExecutionSteps/seq:;segment:2/5:4/5/jumpy-8                                                  757µs ± 2%     753µs ± 2%     ~     (p=0.690 n=5+5)
VariableLoopingVUsGetRawExecutionSteps/seq:;segment:2/5:4/5/rollercoaster-8                                         1.56ms ± 1%    1.56ms ± 1%     ~     (p=1.000 n=5+5)
VariableLoopingVUsGetRawExecutionSteps/seq:;segment:2235/5213:4/5/normal-8                                           164µs ± 1%     164µs ± 2%     ~     (p=0.690 n=5+5)
VariableLoopingVUsGetRawExecutionSteps/seq:;segment:2235/5213:4/5/jumpy-8                                            858µs ± 1%     732µs ± 2%  -14.72%  (p=0.008 n=5+5)
VariableLoopingVUsGetRawExecutionSteps/seq:;segment:2235/5213:4/5/rollercoaster-8                                   1.42ms ± 1%    1.44ms ± 3%     ~     (p=0.310 n=5+5)

name                                                                                                              old alloc/op   new alloc/op   delta
VariableLoopingVUsGetRawExecutionSteps/seq:;segment:/normal-8                                                        246kB ± 0%     246kB ± 0%     ~     (all equal)
VariableLoopingVUsGetRawExecutionSteps/seq:;segment:/jumpy-8                                                        1.29MB ± 0%    1.29MB ± 0%     ~     (p=1.000 n=5+4)
VariableLoopingVUsGetRawExecutionSteps/seq:;segment:/rollercoaster-8                                                2.65MB ± 0%    2.65MB ± 0%     ~     (p=0.095 n=5+4)
VariableLoopingVUsGetRawExecutionSteps/seq:;segment:0:1/normal-8                                                     246kB ± 0%     246kB ± 0%     ~     (all equal)
VariableLoopingVUsGetRawExecutionSteps/seq:;segment:0:1/jumpy-8                                                     1.29MB ± 0%    1.29MB ± 0%   -0.00%  (p=0.016 n=4+5)
VariableLoopingVUsGetRawExecutionSteps/seq:;segment:0:1/rollercoaster-8                                             2.65MB ± 0%    2.65MB ± 0%     ~     (p=1.000 n=5+5)
VariableLoopingVUsGetRawExecutionSteps/seq:0,0.3,0.5,0.6,0.7,0.8,0.9,1;segment:0:0.3/normal-8                       73.8kB ± 0%    73.8kB ± 0%     ~     (all equal)
VariableLoopingVUsGetRawExecutionSteps/seq:0,0.3,0.5,0.6,0.7,0.8,0.9,1;segment:0:0.3/jumpy-8                         393kB ± 0%     393kB ± 0%     ~     (p=0.444 n=5+5)
VariableLoopingVUsGetRawExecutionSteps/seq:0,0.3,0.5,0.6,0.7,0.8,0.9,1;segment:0:0.3/rollercoaster-8                 795kB ± 0%     795kB ± 0%     ~     (p=0.881 n=5+5)
VariableLoopingVUsGetRawExecutionSteps/seq:0,0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1;segment:0:0.1/normal-8           24.6kB ± 0%    24.6kB ± 0%     ~     (all equal)
VariableLoopingVUsGetRawExecutionSteps/seq:0,0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1;segment:0:0.1/jumpy-8             131kB ± 0%     131kB ± 0%     ~     (all equal)
VariableLoopingVUsGetRawExecutionSteps/seq:0,0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1;segment:0:0.1/rollercoaster-8     270kB ± 0%     270kB ± 0%     ~     (p=1.000 n=5+5)
VariableLoopingVUsGetRawExecutionSteps/seq:;segment:2/5:4/5/normal-8                                                98.3kB ± 0%    98.3kB ± 0%     ~     (all equal)
VariableLoopingVUsGetRawExecutionSteps/seq:;segment:2/5:4/5/jumpy-8                                                  516kB ± 0%     516kB ± 0%     ~     (p=0.444 n=5+5)
VariableLoopingVUsGetRawExecutionSteps/seq:;segment:2/5:4/5/rollercoaster-8                                         1.06MB ± 0%    1.06MB ± 0%     ~     (p=0.881 n=5+5)
VariableLoopingVUsGetRawExecutionSteps/seq:;segment:2235/5213:4/5/normal-8                                           172kB ± 0%     172kB ± 0%     ~     (all equal)
VariableLoopingVUsGetRawExecutionSteps/seq:;segment:2235/5213:4/5/jumpy-8                                            565kB ± 0%     565kB ± 0%     ~     (p=1.000 n=5+5)
VariableLoopingVUsGetRawExecutionSteps/seq:;segment:2235/5213:4/5/rollercoaster-8                                   1.06MB ± 0%    1.06MB ± 0%     ~     (p=0.992 n=5+5)

name                                                                                                              old allocs/op  new allocs/op  delta
VariableLoopingVUsGetRawExecutionSteps/seq:;segment:/normal-8                                                         2.00 ± 0%      2.00 ± 0%     ~     (all equal)
VariableLoopingVUsGetRawExecutionSteps/seq:;segment:/jumpy-8                                                          2.00 ± 0%      2.00 ± 0%     ~     (all equal)
VariableLoopingVUsGetRawExecutionSteps/seq:;segment:/rollercoaster-8                                                  2.00 ± 0%      2.00 ± 0%     ~     (all equal)
VariableLoopingVUsGetRawExecutionSteps/seq:;segment:0:1/normal-8                                                      2.00 ± 0%      2.00 ± 0%     ~     (all equal)
VariableLoopingVUsGetRawExecutionSteps/seq:;segment:0:1/jumpy-8                                                       2.00 ± 0%      2.00 ± 0%     ~     (all equal)
VariableLoopingVUsGetRawExecutionSteps/seq:;segment:0:1/rollercoaster-8                                               2.00 ± 0%      2.00 ± 0%     ~     (all equal)
VariableLoopingVUsGetRawExecutionSteps/seq:0,0.3,0.5,0.6,0.7,0.8,0.9,1;segment:0:0.3/normal-8                         2.00 ± 0%      2.00 ± 0%     ~     (all equal)
VariableLoopingVUsGetRawExecutionSteps/seq:0,0.3,0.5,0.6,0.7,0.8,0.9,1;segment:0:0.3/jumpy-8                          2.00 ± 0%      2.00 ± 0%     ~     (all equal)
VariableLoopingVUsGetRawExecutionSteps/seq:0,0.3,0.5,0.6,0.7,0.8,0.9,1;segment:0:0.3/rollercoaster-8                  2.00 ± 0%      2.00 ± 0%     ~     (all equal)
VariableLoopingVUsGetRawExecutionSteps/seq:0,0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1;segment:0:0.1/normal-8             2.00 ± 0%      2.00 ± 0%     ~     (all equal)
VariableLoopingVUsGetRawExecutionSteps/seq:0,0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1;segment:0:0.1/jumpy-8              2.00 ± 0%      2.00 ± 0%     ~     (all equal)
VariableLoopingVUsGetRawExecutionSteps/seq:0,0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1;segment:0:0.1/rollercoaster-8      2.00 ± 0%      2.00 ± 0%     ~     (all equal)
VariableLoopingVUsGetRawExecutionSteps/seq:;segment:2/5:4/5/normal-8                                                  2.00 ± 0%      2.00 ± 0%     ~     (all equal)
VariableLoopingVUsGetRawExecutionSteps/seq:;segment:2/5:4/5/jumpy-8                                                   2.00 ± 0%      2.00 ± 0%     ~     (all equal)
VariableLoopingVUsGetRawExecutionSteps/seq:;segment:2/5:4/5/rollercoaster-8                                           2.00 ± 0%      2.00 ± 0%     ~     (all equal)
VariableLoopingVUsGetRawExecutionSteps/seq:;segment:2235/5213:4/5/normal-8                                            2.00 ± 0%      2.00 ± 0%     ~     (all equal)
VariableLoopingVUsGetRawExecutionSteps/seq:;segment:2235/5213:4/5/jumpy-8                                             2.00 ± 0%      2.00 ± 0%     ~     (all equal)
VariableLoopingVUsGetRawExecutionSteps/seq:;segment:2235/5213:4/5/rollercoaster-8                                     2.00 ± 0%      2.00 ± 0%     ~     (all equal)
  • Loading branch information
mstoykov committed May 17, 2020
1 parent da02b10 commit a2da192
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 19 deletions.
16 changes: 16 additions & 0 deletions lib/execution_segment.go
Original file line number Diff line number Diff line change
Expand Up @@ -623,6 +623,17 @@ func (essw *ExecutionSegmentSequenceWrapper) GetStripedOffsets(segmentIndex int)
return jumps[0], offsets, essw.lcd
}

// GetStripedJumps returns the stripped jumps for the given segment
// the returned values are as follows in order:
// - jumps: a list of jumps from the beginning value for the segment. This are only the jumps
// to from the start to the next start if we chunk the elements we are going to strip
// into lcd sized chunks
// - lcd: the LCD of the lengths of all segments in the sequence. This is also the number of
// elements after which the algorithm starts to loop and give the same values
func (essw *ExecutionSegmentSequenceWrapper) GetStripedJumps(segmentIndex int) ([]int64, int64) {
return essw.jumps[segmentIndex], essw.lcd
}

// GetTuple returns an ExecutionTuple for the specified segment index.
func (essw *ExecutionSegmentSequenceWrapper) GetTuple(segmentIndex int) *ExecutionTuple {
return &ExecutionTuple{
Expand Down Expand Up @@ -723,6 +734,11 @@ func (et *ExecutionTuple) GetStripedOffsets() (int64, []int64, int64) {
return et.Sequence.GetStripedOffsets(et.SegmentIndex)
}

// GetStripedJumps returns the striped jumps for our execution segment.
func (et *ExecutionTuple) GetStripedJumps() ([]int64, int64) {
return et.Sequence.GetStripedJumps(et.SegmentIndex)
}

// GetNewExecutionTupleFromValue re-segments the sequence, based on the given
// value (see GetNewExecutionSegmentSequenceFromValue() above), and either
// returns the new tuple, or an error if the current segment isn't present in
Expand Down
43 changes: 25 additions & 18 deletions lib/executor/variable_looping_vus.go
Original file line number Diff line number Diff line change
Expand Up @@ -186,8 +186,9 @@ func (vlvc VariableLoopingVUsConfig) getRawExecutionSteps(et *lib.ExecutionTuple
timeTillEnd time.Duration
fromVUs = vlvc.StartVUs.Int64
start, offsets, lcd = et.GetStripedOffsets()
jumps, _ = et.GetStripedJumps()
steps = make([]lib.ExecutionStep, 0, vlvc.precalculateTheRequiredSteps(et, zeroEnd))
index = segmentedIndex{start: start, lcd: lcd, offsets: offsets}
index = segmentedIndex{start: start, lcd: lcd, offsets: offsets, jumps: jumps}
)

// Reserve the scaled StartVUs at the beginning
Expand Down Expand Up @@ -248,6 +249,7 @@ func (vlvc VariableLoopingVUsConfig) getRawExecutionSteps(et *lib.ExecutionTuple
type segmentedIndex struct { // TODO: rename ... although this is probably the best name so far :D
start, lcd int64
offsets []int64
jumps []int64
scaled, unscaled int64 // for both the first element(vu) is 1 not 0
}

Expand Down Expand Up @@ -275,36 +277,41 @@ func (s *segmentedIndex) prev() {
// goTo sets the scaled index to it's biggest value for which the corresponding unscaled index is
// is smaller or equal to value
func (s *segmentedIndex) goTo(value int64) int64 { // TODO optimize
var gi int64
// Because of the cyclical nature of the striping algorithm (with a cycle
// length of LCD, the least common denominator), when scaling large values
// (i.e. many multiples of the LCD), we can quickly calculate how many times
// the cycle repeats.
wholeCycles := (value / s.lcd)
// So we can set some approximate initial values quickly, since we also know
// precisely how many scaled values there are per cycle length.
s.scaled = wholeCycles * int64(len(s.offsets))
s.unscaled = wholeCycles*s.lcd + s.start + 1 // our indexes are from 1 the start is from 0
s.scaled = wholeCycles * int64(len(s.jumps))
s.unscaled = wholeCycles * s.lcd // our indexes are from 1 the start is from 0
// Approach the final value using the slow algorithm with the step by step loop
// TODO: this can be optimized by another array with size offsets that instead of the offsets
// from the previous is the offset from either 0 or start
i := s.start
for ; i < value%s.lcd; gi, i = gi+1, i+s.offsets[gi] {
s.scaled++
s.unscaled += s.offsets[gi]
}

if gi > 0 { // there were more values after the wholecycles
// the last offset actually shouldn't have been added
s.unscaled -= s.offsets[gi-1]
} else if s.scaled > 0 { // we didn't actually have more values after the wholecycles but we still had some
remaining := value % s.lcd
switch {
case s.jumps[0]+1 > remaining:
// we didn't actually have more values after the wholecycles but we still had some
// in this case the unscaled value needs to move back by the last offset as it would've been
// the one to get it from the value it needs to be to it's current one
s.unscaled -= s.offsets[len(s.offsets)-1]
}

if s.scaled == 0 {
s.unscaled = 0 // we would've added the start and 1
if wholeCycles > 0 {
s.unscaled -= s.lcd - s.jumps[len(s.jumps)-1] - 1
}
default:
i, j := 0, len(s.jumps)
for i < j {
h := int(uint(i+j) >> 1) // avoid overflow when computing h
// i ≤ h < j
if s.jumps[h] < remaining {
i = h + 1 // preserves f(i-1) == false
} else {
j = h // preserves f(j) == true
}
}
s.scaled += int64(i)
s.unscaled += s.jumps[i-1] + 1
}

return s.scaled
Expand Down
22 changes: 21 additions & 1 deletion lib/executor/variable_looping_vus_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -771,6 +771,26 @@ func BenchmarkVariableLoopingVUsGetRawExecutionSteps(b *testing.B) {
{
name: "normal",
stages: `[{"duration":"5m", "target":5000},{"duration":"5m", "target":5000},{"duration":"5m", "target":10000},{"duration":"5m", "target":10000}]`,
}, {
name: "jumpy",
stages: `[{"duration":"5m", "target":5000},{"duration":"0s", "target":0},
{"duration":"5m", "target":5000},{"duration":"0s", "target":5432},
{"duration":"5m", "target":5000},{"duration":"0s", "target":0},
{"duration":"5m", "target":5000},{"duration":"0s", "target":5432},
{"duration":"5m", "target":5000},{"duration":"0s", "target":0},
{"duration":"5m", "target":5000},{"duration":"0s", "target":5432},
{"duration":"5m", "target":5000},{"duration":"0s", "target":0},
{"duration":"5m", "target":5000},{"duration":"0s", "target":5432},
{"duration":"5m", "target":5000},{"duration":"0s", "target":0},
{"duration":"5m", "target":5000},{"duration":"0s", "target":5432},
{"duration":"5m", "target":5000},{"duration":"0s", "target":0},
{"duration":"5m", "target":5000},{"duration":"0s", "target":5432},
{"duration":"5m", "target":5000},{"duration":"0s", "target":0},
{"duration":"5m", "target":5000},{"duration":"0s", "target":5432},
{"duration":"5m", "target":5000},{"duration":"0s", "target":0},
{"duration":"5m", "target":5000},{"duration":"0s", "target":5432},
{"duration":"5m", "target":5000},{"duration":"0s", "target":0},
{"duration":"5m", "target":5000},{"duration":"0s", "target":5432}]`,
}, {
name: "rollercoaster",
stages: `[{"duration":"5m", "target":5000},{"duration":"5m", "target":0},
Expand Down Expand Up @@ -933,7 +953,7 @@ func TestSegmentedIndex(t *testing.T) {
})

t.Run("strange", func(t *testing.T) {
s := segmentedIndex{start: 1, lcd: 7, offsets: []int64{4, 3}}
s := segmentedIndex{start: 1, lcd: 7, offsets: []int64{4, 3}, jumps: []int64{1, 5}}

s.next()
assert.EqualValues(t, 2, s.unscaled)
Expand Down

0 comments on commit a2da192

Please sign in to comment.