1
1
/*
2
2
* Copyright 2020 by OLTPBenchmark Project
3
3
*
4
- * Licensed under the Apache License, Version 2.0 (the "License");
5
- * you may not use this file except in compliance with the License.
6
- * You may obtain a copy of the License at
4
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5
+ * in compliance with the License. You may obtain a copy of the License at
7
6
*
8
- * http://www.apache.org/licenses/LICENSE-2.0
7
+ * http://www.apache.org/licenses/LICENSE-2.0
9
8
*
10
- * Unless required by applicable law or agreed to in writing, software
11
- * distributed under the License is distributed on an "AS IS" BASIS,
12
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
- * See the License for the specific language governing permissions and
14
- * limitations under the License.
9
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
10
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11
+ * or implied. See the License for the specific language governing permissions and limitations under
12
+ * the License.
15
13
*
16
14
*/
17
15
21
19
import com .oltpbenchmark .api .BenchmarkModule ;
22
20
import com .oltpbenchmark .api .TransactionType ;
23
21
import com .oltpbenchmark .api .Worker ;
22
+ import com .oltpbenchmark .api .collectors .monitoring .Monitor ;
23
+ import com .oltpbenchmark .api .collectors .monitoring .MonitorGen ;
24
24
import com .oltpbenchmark .types .State ;
25
+ import com .oltpbenchmark .util .MonitorInfo ;
25
26
import com .oltpbenchmark .util .StringUtil ;
26
27
import java .util .*;
27
28
import org .apache .commons .collections4 .map .ListOrderedMap ;
30
31
31
32
public class ThreadBench implements Thread .UncaughtExceptionHandler {
32
33
private static final Logger LOG = LoggerFactory .getLogger (ThreadBench .class );
34
+ // Determines how long (in ms) to wait until monitoring thread rejoins the
35
+ // main thread.
36
+ private static final int MONITOR_REJOIN_TIME = 60000 ;
33
37
34
38
private final BenchmarkState testState ;
35
39
private final List <? extends Worker <? extends BenchmarkModule >> workers ;
36
40
private final ArrayList <Thread > workerThreads ;
37
41
private final List <WorkloadConfiguration > workConfs ;
38
42
private final ArrayList <LatencyRecord .Sample > samples = new ArrayList <>();
39
- private final int intervalMonitor ;
43
+ private final MonitorInfo monitorInfo ;
44
+
45
+ private Monitor monitor = null ;
40
46
41
47
private ThreadBench (
42
48
List <? extends Worker <? extends BenchmarkModule >> workers ,
43
49
List <WorkloadConfiguration > workConfs ,
44
- int intervalMonitoring ) {
50
+ MonitorInfo monitorInfo ) {
45
51
this .workers = workers ;
46
52
this .workConfs = workConfs ;
47
53
this .workerThreads = new ArrayList <>(workers .size ());
48
- this .intervalMonitor = intervalMonitoring ;
54
+ this .monitorInfo = monitorInfo ;
49
55
this .testState = new BenchmarkState (workers .size () + 1 );
50
56
}
51
57
52
58
public static Results runRateLimitedBenchmark (
53
59
List <Worker <? extends BenchmarkModule >> workers ,
54
60
List <WorkloadConfiguration > workConfs ,
55
- int intervalMonitoring ) {
56
- ThreadBench bench = new ThreadBench (workers , workConfs , intervalMonitoring );
61
+ MonitorInfo monitorInfo ) {
62
+ ThreadBench bench = new ThreadBench (workers , workConfs , monitorInfo );
57
63
return bench .runRateLimitedMultiPhase ();
58
64
}
59
65
@@ -88,10 +94,9 @@ private int finalizeWorkers(ArrayList<Thread> workerThreads) throws InterruptedE
88
94
// to terminate... hands otherwise
89
95
90
96
/*
91
- * // CARLO: Maybe we might want to do this to kill threads that are
92
- * hanging... if (workerThreads.get(i).isAlive()) {
93
- * workerThreads.get(i).kill(); try { workerThreads.get(i).join(); }
94
- * catch (InterruptedException e) { } }
97
+ * // CARLO: Maybe we might want to do this to kill threads that are hanging... if
98
+ * (workerThreads.get(i).isAlive()) { workerThreads.get(i).kill(); try {
99
+ * workerThreads.get(i).join(); } catch (InterruptedException e) { } }
95
100
*/
96
101
97
102
requests += workers .get (i ).getRequests ();
@@ -116,17 +121,11 @@ private Results runRateLimitedMultiPhase() {
116
121
this .createWorkerThreads ();
117
122
118
123
// long measureStart = start;
124
+ Phase phase = null ;
119
125
120
- long startTs = System .currentTimeMillis ();
121
- long start = System .nanoTime ();
122
- long warmupStart = System .nanoTime ();
123
- long warmup = warmupStart ;
124
- long measureEnd = -1 ;
125
126
// used to determine the longest sleep interval
126
127
double lowestRate = Double .MAX_VALUE ;
127
128
128
- Phase phase = null ;
129
-
130
129
for (WorkloadState workState : workStates ) {
131
130
workState .switchToNextPhase ();
132
131
phase = workState .getCurrentPhase ();
@@ -145,6 +144,12 @@ private Results runRateLimitedMultiPhase() {
145
144
}
146
145
}
147
146
147
+ long startTs = System .currentTimeMillis ();
148
+ long start = System .nanoTime ();
149
+ long warmupStart = System .nanoTime ();
150
+ long warmup = warmupStart ;
151
+ long measureEnd = -1 ;
152
+
148
153
long intervalNs = getInterval (lowestRate , phase .getArrival ());
149
154
150
155
long nextInterval = start + intervalNs ;
@@ -157,8 +162,11 @@ private Results runRateLimitedMultiPhase() {
157
162
boolean lastEntry = false ;
158
163
159
164
// Initialize the Monitor
160
- if (this .intervalMonitor > 0 ) {
161
- new MonitorThread (this .intervalMonitor ).start ();
165
+ if (this .monitorInfo .getMonitoringInterval () > 0 ) {
166
+ this .monitor =
167
+ MonitorGen .getMonitor (
168
+ this .monitorInfo , this .testState , this .workers , this .workConfs .get (0 ));
169
+ this .monitor .start ();
162
170
}
163
171
164
172
// Allow workers to start work.
@@ -301,6 +309,18 @@ private Results runRateLimitedMultiPhase() {
301
309
}
302
310
}
303
311
312
+ // Stop the monitoring thread separately from cleanup all the workers so we can ignore errors
313
+ // from these threads (including possible SQLExceptions), but not the others.
314
+ try {
315
+ if (this .monitor != null ) {
316
+ this .monitor .interrupt ();
317
+ this .monitor .join (MONITOR_REJOIN_TIME );
318
+ this .monitor .tearDown ();
319
+ }
320
+ } catch (Exception e ) {
321
+ LOG .error (e .getMessage (), e );
322
+ }
323
+
304
324
try {
305
325
int requests = finalizeWorkers (this .workerThreads );
306
326
@@ -528,42 +548,4 @@ public void run() {
528
548
}
529
549
}
530
550
}
531
-
532
- private class MonitorThread extends Thread {
533
- private final int intervalMonitor ;
534
-
535
- {
536
- this .setDaemon (true );
537
- }
538
-
539
- /**
540
- * @param interval How long to wait between polling in milliseconds
541
- */
542
- MonitorThread (int interval ) {
543
- this .intervalMonitor = interval ;
544
- }
545
-
546
- @ Override
547
- public void run () {
548
- LOG .info ("Starting MonitorThread Interval [{}ms]" , this .intervalMonitor );
549
- while (true ) {
550
- try {
551
- Thread .sleep (this .intervalMonitor );
552
- } catch (InterruptedException ex ) {
553
- return ;
554
- }
555
-
556
- // Compute the last throughput
557
- long measuredRequests = 0 ;
558
- synchronized (testState ) {
559
- for (Worker <?> w : workers ) {
560
- measuredRequests += w .getAndResetIntervalRequests ();
561
- }
562
- }
563
- double seconds = this .intervalMonitor / 1000d ;
564
- double tps = (double ) measuredRequests / seconds ;
565
- LOG .info ("Throughput: {} txn/sec" , tps );
566
- }
567
- }
568
- }
569
551
}
0 commit comments