25
25
/*
26
26
* This throughput generator configures throughput with a gaussian normal distribution on a per-window basis. You can
27
27
* specify how many windows to keep the throughput at the rate before changing. All traffic will follow a gaussian
28
- * distribution centered around `messagesPerSecondAverage ` with a deviation of `messagesPerSecondDeviation `.
28
+ * distribution centered around `messagesPerWindowAverage ` with a deviation of `messagesPerWindowDeviation `.
29
29
*
30
30
* The lower the window size, the smoother the traffic will be. Using a 100ms window offers no noticeable spikes in
31
31
* traffic while still being long enough to avoid too much overhead.
32
32
*
33
- * WARNING: Due to binary nature of throughput in terms of messages sent in a window, this does not work well for an
34
- * average throughput of less than 5 messages per window. In cases where you want lower throughput, please adjust the
35
- * `windowSizeMs` accordingly.
36
- *
37
33
* Here is an example spec:
38
34
*
39
35
* {
40
36
* "type": "gaussian",
41
- * "messagesPerSecondAverage ": 500 ,
42
- * "messagesPerSecondDeviation ": 50 ,
37
+ * "messagesPerWindowAverage ": 50 ,
38
+ * "messagesPerWindowDeviation ": 5 ,
43
39
* "windowsUntilRateChange": 100,
44
40
* "windowSizeMs": 100
45
41
* }
56
52
*/
57
53
58
54
public class GaussianThroughputGenerator implements ThroughputGenerator {
59
- private final int messagesPerSecondAverage ;
60
- private final int messagesPerSecondDeviation ;
61
55
private final int messagesPerWindowAverage ;
62
- private final int messagesPerWindowDeviation ;
56
+ private final double messagesPerWindowDeviation ;
63
57
private final int windowsUntilRateChange ;
64
58
private final long windowSizeMs ;
65
59
@@ -71,42 +65,43 @@ public class GaussianThroughputGenerator implements ThroughputGenerator {
71
65
private int throttleMessages = 0 ;
72
66
73
67
@ JsonCreator
74
- public GaussianThroughputGenerator (@ JsonProperty ("messagesPerSecondAverage " ) int messagesPerSecondAverage ,
75
- @ JsonProperty ("messagesPerSecondDeviation " ) int messagesPerSecondDeviation ,
68
+ public GaussianThroughputGenerator (@ JsonProperty ("messagesPerWindowAverage " ) int messagesPerWindowAverage ,
69
+ @ JsonProperty ("messagesPerWindowDeviation " ) double messagesPerWindowDeviation ,
76
70
@ JsonProperty ("windowsUntilRateChange" ) int windowsUntilRateChange ,
77
71
@ JsonProperty ("windowSizeMs" ) long windowSizeMs ) {
78
- // Calcualte the default values.
72
+ // Calculate the default values.
79
73
if (windowSizeMs <= 0 ) {
80
74
windowSizeMs = 100 ;
81
75
}
82
76
this .windowSizeMs = windowSizeMs ;
83
- this .messagesPerSecondAverage = messagesPerSecondAverage ;
84
- this .messagesPerSecondDeviation = messagesPerSecondDeviation ;
77
+ this .messagesPerWindowAverage = messagesPerWindowAverage ;
78
+ this .messagesPerWindowDeviation = messagesPerWindowDeviation ;
85
79
this .windowsUntilRateChange = windowsUntilRateChange ;
86
80
87
- // Take per-second calculations and convert them to per-window calculations.
88
- messagesPerWindowAverage = (int ) (messagesPerSecondAverage * windowSizeMs / 1000 );
89
- messagesPerWindowDeviation = (int ) (messagesPerSecondDeviation * windowSizeMs / 1000 );
90
-
91
- // Calcualte the first window.
81
+ // Calculate the first window.
92
82
calculateNextWindow (true );
93
83
}
94
84
95
85
@ JsonProperty
96
- public int messagesPerSecondAverage () {
97
- return messagesPerSecondAverage ;
86
+ public int messagesPerWindowAverage () {
87
+ return messagesPerWindowAverage ;
98
88
}
99
89
100
90
@ JsonProperty
101
- public long messagesPerSecondDeviation () {
102
- return messagesPerSecondDeviation ;
91
+ public double messagesPerWindowDeviation () {
92
+ return messagesPerWindowDeviation ;
103
93
}
104
94
105
95
@ JsonProperty
106
96
public long windowsUntilRateChange () {
107
97
return windowsUntilRateChange ;
108
98
}
109
99
100
+ @ JsonProperty
101
+ public long windowSizeMs () {
102
+ return windowSizeMs ;
103
+ }
104
+
110
105
private synchronized void calculateNextWindow (boolean force ) {
111
106
// Reset the message count.
112
107
messageTracker = 0 ;
@@ -127,7 +122,7 @@ private synchronized void calculateNextWindow(boolean force) {
127
122
128
123
// Calculate the number of messages allowed in this window using a normal distribution.
129
124
// The formula is: Messages = Gaussian * Deviation + Average
130
- throttleMessages = Math .max ((int ) (random .nextGaussian () * ( double ) messagesPerWindowDeviation ) + messagesPerWindowAverage , 1 );
125
+ throttleMessages = Math .max ((int ) (random .nextGaussian () * messagesPerWindowDeviation ) + messagesPerWindowAverage , 1 );
131
126
}
132
127
windowTracker += 1 ;
133
128
}
@@ -146,7 +141,9 @@ public synchronized void throttle() throws InterruptedException {
146
141
if (messageTracker >= throttleMessages ) {
147
142
148
143
// Wait the difference in time between now and when the next window starts.
149
- wait (nextWindowStarts - Time .SYSTEM .milliseconds ());
144
+ while (nextWindowStarts > Time .SYSTEM .milliseconds ()) {
145
+ wait (nextWindowStarts - Time .SYSTEM .milliseconds ());
146
+ }
150
147
}
151
148
}
152
149
}
0 commit comments