forked from vdobler/ht
-
Notifications
You must be signed in to change notification settings - Fork 0
/
bender.go
147 lines (124 loc) · 3.88 KB
/
bender.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
/*
Copyright 2014 Pinterest.com
Copyright 2016 Volker Dobler.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package bender
import (
"math"
"sync"
"time"
"github.com/vdobler/ht/ht"
)
type IntervalGenerator func(int64) int64
type EventType int
const (
StartEvent EventType = iota
EndEvent
WaitEvent
StartRequestEvent
EndRequestEvent
)
var eventName = []string{"Begin", "Finish", "Wait", "StartReq", "EndReq"}
type Event struct {
Typ EventType
Start, End int64
Wait, Overage int64
Test *ht.Test
Err error
}
type Test struct {
Test *ht.Test
Done chan bool
}
/******
// StartEvent is sent once at the start of the load test.
// The Unix epoch time in nanoseconds at which the load test started.
Start int64
// EndEvent is sent once at the end of the load test, after which no more
// events are sent.
// The Unix epoch times in nanoseconds at which the load test
// started and ended.
Start, End int64
// WaitEvent is sent once for each request before sleeping for the given
// interval.
// The next wait time (in nanoseconds) and the accumulated overage
// time (the difference between
// the actual wait time and the intended wait time).
Wait, Overage int64
// StartRequestEvent is sent before a request is executed. The sending of this
// event happens before the timing of the request starts, to avoid potential
// issues, so it contains the timestamp of the event send, and not the
// timestamp of the request start.
// The Unix epoch time (in nanoseconds) at which this event was
// created, which will be earlier
// than the sending of the associated request (for performance reasons)
Time int64
// The request that will be sent, nothing good can come from modifying it
Request *ht.Test
// EndRequestEvent is sent after a request has completed.
// The Unix epoch times (in nanoseconds) at which the request was
// started and finished
Start, End int64
// The response data returned by the request executor
Response *ht.Test
************/
// LoadTestThroughput starts a load test in which the caller controls the
// interval between requests being sent. See the package documentation for
// details on the arguments to this function.
func LoadTestThroughput(intervals IntervalGenerator, requests chan Test, recorder chan Event) {
go func() {
start := time.Now().UnixNano()
recorder <- Event{Typ: StartEvent, Start: start}
var wg sync.WaitGroup
var overage int64
overageStart := time.Now().UnixNano()
for request := range requests {
wait := intervals(overageStart)
adjust := int64(math.Min(float64(wait), float64(overage)))
wait -= adjust
overage -= adjust
// recorder <- Event{Typ: WaitEvent, Wait: wait, Overage: overage}
time.Sleep(time.Duration(wait))
wg.Add(1)
go func(test Test, overage int64) {
defer wg.Done()
/*
recorder <- Event{
Typ: StartRequestEvent,
Start: time.Now().UnixNano(),
Test: test.Test,
}
*/
reqStart := time.Now().UnixNano()
test.Test.Run()
test.Done <- true
recorder <- Event{
Typ: EndRequestEvent,
Start: reqStart,
End: time.Now().UnixNano(),
Wait: wait,
Overage: overage,
Test: test.Test,
}
}(request, overage)
overage += time.Now().UnixNano() - overageStart - wait
overageStart = time.Now().UnixNano()
}
wg.Wait()
recorder <- Event{
Typ: EndEvent,
Start: start,
End: time.Now().UnixNano(),
}
close(recorder)
}()
}