blob: 7e74aac8744c6f795a146cd658e0d5aacd2b0dc7 [file] [log] [blame]
Marc Slemkoc7782972006-07-25 02:26:35 +00001#include <config.h>
Marc Slemko6f038a72006-08-03 18:58:09 +00002#include <concurrency/ThreadManager.h>
3#include <concurrency/PosixThreadFactory.h>
4#include <concurrency/Monitor.h>
5#include <concurrency/Util.h>
Marc Slemko740343d2006-07-20 00:31:02 +00006
7#include <assert.h>
8#include <set>
9#include <iostream>
Marc Slemkoc7782972006-07-25 02:26:35 +000010#include <set>
11#include <stdint.h>
Marc Slemko740343d2006-07-20 00:31:02 +000012
13namespace facebook { namespace thrift { namespace concurrency { namespace test {
14
15using namespace facebook::thrift::concurrency;
16
17/** ThreadManagerTests class
18
19 @author marc
20 @version $Id:$ */
21
22class ThreadManagerTests {
23
24public:
25
Marc Slemko6f038a72006-08-03 18:58:09 +000026 static const double ERROR;
27
Marc Slemko740343d2006-07-20 00:31:02 +000028 class Task: public Runnable {
29
30 public:
31
32 Task(Monitor& monitor, size_t& count, long long timeout) :
33 _monitor(monitor),
34 _count(count),
35 _timeout(timeout),
Marc Slemko740343d2006-07-20 00:31:02 +000036 _done(false) {}
37
38 void run() {
39
Marc Slemkoc7782972006-07-25 02:26:35 +000040 _startTime = Util::currentTime();
Marc Slemko740343d2006-07-20 00:31:02 +000041
Marc Slemkoc7782972006-07-25 02:26:35 +000042 {Synchronized s(_sleep);
Marc Slemko740343d2006-07-20 00:31:02 +000043
Marc Slemko740343d2006-07-20 00:31:02 +000044
Marc Slemkoc7782972006-07-25 02:26:35 +000045 _sleep.wait(_timeout);
Marc Slemkofe5ba12e2006-07-20 21:16:27 +000046 }
Marc Slemko740343d2006-07-20 00:31:02 +000047
Marc Slemkoc7782972006-07-25 02:26:35 +000048 _endTime = Util::currentTime();
49
Marc Slemko740343d2006-07-20 00:31:02 +000050 _done = true;
51
Marc Slemko740343d2006-07-20 00:31:02 +000052 {Synchronized s(_monitor);
53
54 // std::cout << "Thread " << _count << " completed " << std::endl;
55
56 _count--;
57
58 if(_count == 0) {
59
60 _monitor.notify();
61 }
62 }
63 }
64
65 Monitor& _monitor;
66 size_t& _count;
67 long long _timeout;
Marc Slemkoc7782972006-07-25 02:26:35 +000068 long long _startTime;
69 long long _endTime;
Marc Slemko740343d2006-07-20 00:31:02 +000070 bool _done;
Marc Slemkoc7782972006-07-25 02:26:35 +000071 Monitor _sleep;
Marc Slemko740343d2006-07-20 00:31:02 +000072 };
73
74 /** Dispatch count tasks, each of which blocks for timeout milliseconds then completes.
75 Verify that all tasks completed and that thread manager cleans up properly on delete. */
76
Marc Slemkofe5ba12e2006-07-20 21:16:27 +000077 bool loadTest(size_t count=100, long long timeout=100LL, size_t workerCount=4) {
Marc Slemko740343d2006-07-20 00:31:02 +000078
79 Monitor monitor;
80
81 size_t activeCount = count;
82
Marc Slemko6f038a72006-08-03 18:58:09 +000083 shared_ptr<ThreadManager> threadManager = ThreadManager::newSimpleThreadManager(workerCount);
Marc Slemkoc7782972006-07-25 02:26:35 +000084
Marc Slemko6f038a72006-08-03 18:58:09 +000085 shared_ptr<PosixThreadFactory> threadFactory = shared_ptr<PosixThreadFactory>(new PosixThreadFactory());
Marc Slemkoc7782972006-07-25 02:26:35 +000086
87 threadFactory->priority(PosixThreadFactory::HIGHEST);
Marc Slemko740343d2006-07-20 00:31:02 +000088
Marc Slemkoc7782972006-07-25 02:26:35 +000089 threadManager->threadFactory(threadFactory);
Marc Slemkofe5ba12e2006-07-20 21:16:27 +000090
91 threadManager->start();
Marc Slemko740343d2006-07-20 00:31:02 +000092
Marc Slemko6f038a72006-08-03 18:58:09 +000093 std::set<shared_ptr<ThreadManagerTests::Task> > tasks;
Marc Slemko740343d2006-07-20 00:31:02 +000094
95 for(size_t ix = 0; ix < count; ix++) {
96
Marc Slemko6f038a72006-08-03 18:58:09 +000097 tasks.insert(shared_ptr<ThreadManagerTests::Task>(new ThreadManagerTests::Task(monitor, activeCount, timeout)));
Marc Slemko740343d2006-07-20 00:31:02 +000098 }
99
Marc Slemkofe5ba12e2006-07-20 21:16:27 +0000100 long long time00 = Util::currentTime();
101
Marc Slemko6f038a72006-08-03 18:58:09 +0000102 for(std::set<shared_ptr<ThreadManagerTests::Task> >::iterator ix = tasks.begin(); ix != tasks.end(); ix++) {
Marc Slemko740343d2006-07-20 00:31:02 +0000103
104 threadManager->add(*ix);
105 }
106
107 {Synchronized s(monitor);
108
109 while(activeCount > 0) {
110
111 monitor.wait();
112 }
113 }
114
Marc Slemkofe5ba12e2006-07-20 21:16:27 +0000115 long long time01 = Util::currentTime();
Marc Slemko740343d2006-07-20 00:31:02 +0000116
Marc Slemkoc7782972006-07-25 02:26:35 +0000117 long long firstTime = 9223372036854775807LL;
118 long long lastTime = 0;
119
120 double averageTime = 0;
121 long long minTime = 9223372036854775807LL;
122 long long maxTime = 0;
123
Marc Slemko6f038a72006-08-03 18:58:09 +0000124 for(std::set<shared_ptr<ThreadManagerTests::Task> >::iterator ix = tasks.begin(); ix != tasks.end(); ix++) {
Marc Slemkoc7782972006-07-25 02:26:35 +0000125
Marc Slemko6f038a72006-08-03 18:58:09 +0000126 shared_ptr<ThreadManagerTests::Task> task = *ix;
Marc Slemkoc7782972006-07-25 02:26:35 +0000127
128 long long delta = task->_endTime - task->_startTime;
129
130 assert(delta > 0);
131
132 if(task->_startTime < firstTime) {
133 firstTime = task->_startTime;
134 }
135
136 if(task->_endTime > lastTime) {
137 lastTime = task->_endTime;
138 }
139
140 if(delta < minTime) {
141 minTime = delta;
142 }
143
144 if(delta > maxTime) {
145 maxTime = delta;
146 }
147
148 averageTime+= delta;
Marc Slemko740343d2006-07-20 00:31:02 +0000149 }
Marc Slemkoc7782972006-07-25 02:26:35 +0000150
151 averageTime /= count;
152
153 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 +0000154
Marc Slemkofe5ba12e2006-07-20 21:16:27 +0000155 double expectedTime = ((count + (workerCount - 1)) / workerCount) * timeout;
156
157 double error = ((time01 - time00) - expectedTime) / expectedTime;
158
159 if(error < 0) {
160 error*= -1.0;
161 }
162
Marc Slemko6f038a72006-08-03 18:58:09 +0000163 bool success = error < ERROR;
Marc Slemkoc7782972006-07-25 02:26:35 +0000164
Marc Slemkofe5ba12e2006-07-20 21:16:27 +0000165 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 +0000166
Marc Slemkoc7782972006-07-25 02:26:35 +0000167 return success;
Marc Slemko740343d2006-07-20 00:31:02 +0000168 }
169};
Marc Slemko6f038a72006-08-03 18:58:09 +0000170
171const double ThreadManagerTests::ERROR = .20;
172
Marc Slemko740343d2006-07-20 00:31:02 +0000173}}}} // facebook::thrift::concurrency
174
175using namespace facebook::thrift::concurrency::test;
176