blob: 8b2dda8b061a9da550f4745e2ace63947cd968a0 [file] [log] [blame]
Marc Slemkoc7782972006-07-25 02:26:35 +00001#include <config.h>
Marc Slemko740343d2006-07-20 00:31:02 +00002#include <ThreadManager.h>
3#include <PosixThreadFactory.h>
4#include <Monitor.h>
5#include <Util.h>
6
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
26 class Task: public Runnable {
27
28 public:
29
30 Task(Monitor& monitor, size_t& count, long long timeout) :
31 _monitor(monitor),
32 _count(count),
33 _timeout(timeout),
Marc Slemko740343d2006-07-20 00:31:02 +000034 _done(false) {}
35
36 void run() {
37
Marc Slemkoc7782972006-07-25 02:26:35 +000038 _startTime = Util::currentTime();
Marc Slemko740343d2006-07-20 00:31:02 +000039
Marc Slemkoc7782972006-07-25 02:26:35 +000040 {Synchronized s(_sleep);
Marc Slemko740343d2006-07-20 00:31:02 +000041
Marc Slemko740343d2006-07-20 00:31:02 +000042
Marc Slemkoc7782972006-07-25 02:26:35 +000043 _sleep.wait(_timeout);
Marc Slemkofe5ba12e2006-07-20 21:16:27 +000044 }
Marc Slemko740343d2006-07-20 00:31:02 +000045
Marc Slemkoc7782972006-07-25 02:26:35 +000046 _endTime = Util::currentTime();
47
Marc Slemko740343d2006-07-20 00:31:02 +000048 _done = true;
49
Marc Slemko740343d2006-07-20 00:31:02 +000050 {Synchronized s(_monitor);
51
52 // std::cout << "Thread " << _count << " completed " << std::endl;
53
54 _count--;
55
56 if(_count == 0) {
57
58 _monitor.notify();
59 }
60 }
61 }
62
63 Monitor& _monitor;
64 size_t& _count;
65 long long _timeout;
Marc Slemkoc7782972006-07-25 02:26:35 +000066 long long _startTime;
67 long long _endTime;
Marc Slemko740343d2006-07-20 00:31:02 +000068 bool _done;
Marc Slemkoc7782972006-07-25 02:26:35 +000069 Monitor _sleep;
Marc Slemko740343d2006-07-20 00:31:02 +000070 };
71
72 /** Dispatch count tasks, each of which blocks for timeout milliseconds then completes.
73 Verify that all tasks completed and that thread manager cleans up properly on delete. */
74
Marc Slemkofe5ba12e2006-07-20 21:16:27 +000075 bool loadTest(size_t count=100, long long timeout=100LL, size_t workerCount=4) {
Marc Slemko740343d2006-07-20 00:31:02 +000076
77 Monitor monitor;
78
79 size_t activeCount = count;
80
81 ThreadManager* threadManager = ThreadManager::newSimpleThreadManager(workerCount);
Marc Slemkoc7782972006-07-25 02:26:35 +000082
83 PosixThreadFactory* threadFactory = new PosixThreadFactory();
84
85 threadFactory->priority(PosixThreadFactory::HIGHEST);
Marc Slemko740343d2006-07-20 00:31:02 +000086
Marc Slemkoc7782972006-07-25 02:26:35 +000087 threadManager->threadFactory(threadFactory);
Marc Slemkofe5ba12e2006-07-20 21:16:27 +000088
89 threadManager->start();
Marc Slemko740343d2006-07-20 00:31:02 +000090
91 std::set<ThreadManagerTests::Task*> tasks;
92
93 for(size_t ix = 0; ix < count; ix++) {
94
95 tasks.insert(new ThreadManagerTests::Task(monitor, activeCount, timeout));
96 }
97
Marc Slemkofe5ba12e2006-07-20 21:16:27 +000098 long long time00 = Util::currentTime();
99
Marc Slemko740343d2006-07-20 00:31:02 +0000100 for(std::set<ThreadManagerTests::Task*>::iterator ix = tasks.begin(); ix != tasks.end(); ix++) {
101
102 threadManager->add(*ix);
103 }
104
105 {Synchronized s(monitor);
106
107 while(activeCount > 0) {
108
109 monitor.wait();
110 }
111 }
112
Marc Slemkofe5ba12e2006-07-20 21:16:27 +0000113 long long time01 = Util::currentTime();
Marc Slemko740343d2006-07-20 00:31:02 +0000114
Marc Slemkoc7782972006-07-25 02:26:35 +0000115 long long firstTime = 9223372036854775807LL;
116 long long lastTime = 0;
117
118 double averageTime = 0;
119 long long minTime = 9223372036854775807LL;
120 long long maxTime = 0;
121
Marc Slemko740343d2006-07-20 00:31:02 +0000122 for(std::set<ThreadManagerTests::Task*>::iterator ix = tasks.begin(); ix != tasks.end(); ix++) {
Marc Slemkoc7782972006-07-25 02:26:35 +0000123
124 ThreadManagerTests::Task* task = *ix;
125
126 long long delta = task->_endTime - task->_startTime;
127
128 assert(delta > 0);
129
130 if(task->_startTime < firstTime) {
131 firstTime = task->_startTime;
132 }
133
134 if(task->_endTime > lastTime) {
135 lastTime = task->_endTime;
136 }
137
138 if(delta < minTime) {
139 minTime = delta;
140 }
141
142 if(delta > maxTime) {
143 maxTime = delta;
144 }
145
146 averageTime+= delta;
Marc Slemko740343d2006-07-20 00:31:02 +0000147
Marc Slemko740343d2006-07-20 00:31:02 +0000148 delete *ix;
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
163 bool success = error < .10;
164
Marc Slemko740343d2006-07-20 00:31:02 +0000165 delete threadManager;
166
Marc Slemkoc7782972006-07-25 02:26:35 +0000167 delete threadFactory;
168
Marc Slemkofe5ba12e2006-07-20 21:16:27 +0000169 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 +0000170
Marc Slemkoc7782972006-07-25 02:26:35 +0000171 return success;
Marc Slemko740343d2006-07-20 00:31:02 +0000172 }
173};
174
175}}}} // facebook::thrift::concurrency
176
177using namespace facebook::thrift::concurrency::test;
178