blob: 9f04435473303b23af3dea9aa1a3a37fb334d256 [file] [log] [blame]
Mark Slee9f0c6512007-02-28 23:58:26 +00001// Copyright (c) 2006- Facebook
2// Distributed under the Thrift Software License
3//
4// See accompanying file LICENSE or visit the Thrift site at:
5// http://developers.facebook.com/thrift/
6
Marc Slemkoc7782972006-07-25 02:26:35 +00007#include <config.h>
Marc Slemko6f038a72006-08-03 18:58:09 +00008#include <concurrency/ThreadManager.h>
9#include <concurrency/PosixThreadFactory.h>
10#include <concurrency/Monitor.h>
11#include <concurrency/Util.h>
Marc Slemko740343d2006-07-20 00:31:02 +000012
13#include <assert.h>
14#include <set>
15#include <iostream>
Marc Slemkoc7782972006-07-25 02:26:35 +000016#include <set>
17#include <stdint.h>
Marc Slemko740343d2006-07-20 00:31:02 +000018
19namespace facebook { namespace thrift { namespace concurrency { namespace test {
20
21using namespace facebook::thrift::concurrency;
22
Mark Sleef5f2be42006-09-05 21:05:31 +000023/**
24 * ThreadManagerTests class
25 *
26 * @author marc
27 * @version $Id:$
28 */
Marc Slemko740343d2006-07-20 00:31:02 +000029class ThreadManagerTests {
30
31public:
32
Marc Slemko6f038a72006-08-03 18:58:09 +000033 static const double ERROR;
34
Marc Slemko740343d2006-07-20 00:31:02 +000035 class Task: public Runnable {
36
37 public:
38
39 Task(Monitor& monitor, size_t& count, long long timeout) :
40 _monitor(monitor),
41 _count(count),
42 _timeout(timeout),
Marc Slemko740343d2006-07-20 00:31:02 +000043 _done(false) {}
44
45 void run() {
46
Marc Slemkoc7782972006-07-25 02:26:35 +000047 _startTime = Util::currentTime();
Marc Slemko740343d2006-07-20 00:31:02 +000048
Mark Sleef5f2be42006-09-05 21:05:31 +000049 {
50 Synchronized s(_sleep);
Marc Slemko740343d2006-07-20 00:31:02 +000051
Marc Slemkoc7782972006-07-25 02:26:35 +000052 _sleep.wait(_timeout);
Marc Slemkofe5ba12e2006-07-20 21:16:27 +000053 }
Marc Slemko740343d2006-07-20 00:31:02 +000054
Marc Slemkoc7782972006-07-25 02:26:35 +000055 _endTime = Util::currentTime();
56
Marc Slemko740343d2006-07-20 00:31:02 +000057 _done = true;
58
Mark Sleef5f2be42006-09-05 21:05:31 +000059 {
60 Synchronized s(_monitor);
Marc Slemko740343d2006-07-20 00:31:02 +000061
62 // std::cout << "Thread " << _count << " completed " << std::endl;
63
64 _count--;
65
Mark Sleef5f2be42006-09-05 21:05:31 +000066 if (_count == 0) {
Marc Slemko740343d2006-07-20 00:31:02 +000067
68 _monitor.notify();
69 }
70 }
71 }
72
73 Monitor& _monitor;
74 size_t& _count;
75 long long _timeout;
Marc Slemkoc7782972006-07-25 02:26:35 +000076 long long _startTime;
77 long long _endTime;
Marc Slemko740343d2006-07-20 00:31:02 +000078 bool _done;
Marc Slemkoc7782972006-07-25 02:26:35 +000079 Monitor _sleep;
Marc Slemko740343d2006-07-20 00:31:02 +000080 };
81
Mark Sleef5f2be42006-09-05 21:05:31 +000082 /**
83 * Dispatch count tasks, each of which blocks for timeout milliseconds then
84 * completes. Verify that all tasks completed and that thread manager cleans
85 * up properly on delete.
86 */
Marc Slemkofe5ba12e2006-07-20 21:16:27 +000087 bool loadTest(size_t count=100, long long timeout=100LL, size_t workerCount=4) {
Marc Slemko740343d2006-07-20 00:31:02 +000088
89 Monitor monitor;
90
91 size_t activeCount = count;
92
Marc Slemko6f038a72006-08-03 18:58:09 +000093 shared_ptr<ThreadManager> threadManager = ThreadManager::newSimpleThreadManager(workerCount);
Marc Slemkoc7782972006-07-25 02:26:35 +000094
Marc Slemko6f038a72006-08-03 18:58:09 +000095 shared_ptr<PosixThreadFactory> threadFactory = shared_ptr<PosixThreadFactory>(new PosixThreadFactory());
Marc Slemkoc7782972006-07-25 02:26:35 +000096
97 threadFactory->priority(PosixThreadFactory::HIGHEST);
Marc Slemko740343d2006-07-20 00:31:02 +000098
Marc Slemkoc7782972006-07-25 02:26:35 +000099 threadManager->threadFactory(threadFactory);
Marc Slemkofe5ba12e2006-07-20 21:16:27 +0000100
101 threadManager->start();
Marc Slemko740343d2006-07-20 00:31:02 +0000102
Marc Slemko6f038a72006-08-03 18:58:09 +0000103 std::set<shared_ptr<ThreadManagerTests::Task> > tasks;
Marc Slemko740343d2006-07-20 00:31:02 +0000104
Mark Sleef5f2be42006-09-05 21:05:31 +0000105 for (size_t ix = 0; ix < count; ix++) {
Marc Slemko740343d2006-07-20 00:31:02 +0000106
Marc Slemko6f038a72006-08-03 18:58:09 +0000107 tasks.insert(shared_ptr<ThreadManagerTests::Task>(new ThreadManagerTests::Task(monitor, activeCount, timeout)));
Marc Slemko740343d2006-07-20 00:31:02 +0000108 }
109
Marc Slemkofe5ba12e2006-07-20 21:16:27 +0000110 long long time00 = Util::currentTime();
111
Mark Sleef5f2be42006-09-05 21:05:31 +0000112 for (std::set<shared_ptr<ThreadManagerTests::Task> >::iterator ix = tasks.begin(); ix != tasks.end(); ix++) {
Marc Slemko740343d2006-07-20 00:31:02 +0000113
114 threadManager->add(*ix);
115 }
116
Mark Sleef5f2be42006-09-05 21:05:31 +0000117 {
118 Synchronized s(monitor);
119
Marc Slemko740343d2006-07-20 00:31:02 +0000120 while(activeCount > 0) {
121
122 monitor.wait();
123 }
124 }
125
Marc Slemkofe5ba12e2006-07-20 21:16:27 +0000126 long long time01 = Util::currentTime();
Marc Slemko740343d2006-07-20 00:31:02 +0000127
Marc Slemkoc7782972006-07-25 02:26:35 +0000128 long long firstTime = 9223372036854775807LL;
129 long long lastTime = 0;
130
131 double averageTime = 0;
132 long long minTime = 9223372036854775807LL;
133 long long maxTime = 0;
134
Mark Sleef5f2be42006-09-05 21:05:31 +0000135 for (std::set<shared_ptr<ThreadManagerTests::Task> >::iterator ix = tasks.begin(); ix != tasks.end(); ix++) {
Marc Slemkoc7782972006-07-25 02:26:35 +0000136
Marc Slemko6f038a72006-08-03 18:58:09 +0000137 shared_ptr<ThreadManagerTests::Task> task = *ix;
Marc Slemkoc7782972006-07-25 02:26:35 +0000138
139 long long delta = task->_endTime - task->_startTime;
140
141 assert(delta > 0);
142
Mark Sleef5f2be42006-09-05 21:05:31 +0000143 if (task->_startTime < firstTime) {
Marc Slemkoc7782972006-07-25 02:26:35 +0000144 firstTime = task->_startTime;
145 }
146
Mark Sleef5f2be42006-09-05 21:05:31 +0000147 if (task->_endTime > lastTime) {
Marc Slemkoc7782972006-07-25 02:26:35 +0000148 lastTime = task->_endTime;
149 }
150
Mark Sleef5f2be42006-09-05 21:05:31 +0000151 if (delta < minTime) {
Marc Slemkoc7782972006-07-25 02:26:35 +0000152 minTime = delta;
153 }
154
Mark Sleef5f2be42006-09-05 21:05:31 +0000155 if (delta > maxTime) {
Marc Slemkoc7782972006-07-25 02:26:35 +0000156 maxTime = delta;
157 }
158
159 averageTime+= delta;
Marc Slemko740343d2006-07-20 00:31:02 +0000160 }
Marc Slemkoc7782972006-07-25 02:26:35 +0000161
162 averageTime /= count;
163
164 std::cout << "\t\t\tfirst start: " << firstTime << "ms Last end: " << lastTime << "ms min: " << minTime << "ms max: " << maxTime << "ms average: " << averageTime << "ms" << std::endl;
Marc Slemko740343d2006-07-20 00:31:02 +0000165
Marc Slemkofe5ba12e2006-07-20 21:16:27 +0000166 double expectedTime = ((count + (workerCount - 1)) / workerCount) * timeout;
167
168 double error = ((time01 - time00) - expectedTime) / expectedTime;
169
Mark Sleef5f2be42006-09-05 21:05:31 +0000170 if (error < 0) {
Marc Slemkofe5ba12e2006-07-20 21:16:27 +0000171 error*= -1.0;
172 }
173
Marc Slemko6f038a72006-08-03 18:58:09 +0000174 bool success = error < ERROR;
Marc Slemkoc7782972006-07-25 02:26:35 +0000175
Marc Slemkofe5ba12e2006-07-20 21:16:27 +0000176 std::cout << "\t\t\t" << (success ? "Success" : "Failure") << "! expected time: " << expectedTime << "ms elapsed time: "<< time01 - time00 << "ms error%: " << error * 100.0 << std::endl;
Marc Slemko740343d2006-07-20 00:31:02 +0000177
Marc Slemkoc7782972006-07-25 02:26:35 +0000178 return success;
Marc Slemko740343d2006-07-20 00:31:02 +0000179 }
180};
Marc Slemko6f038a72006-08-03 18:58:09 +0000181
182const double ThreadManagerTests::ERROR = .20;
183
Marc Slemko740343d2006-07-20 00:31:02 +0000184}}}} // facebook::thrift::concurrency
185
186using namespace facebook::thrift::concurrency::test;
187