blob: e17434353a5397f690399b60e8190f42c894245a [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
Mark Sleef5f2be42006-09-05 21:05:31 +000017/**
18 * ThreadManagerTests class
19 *
20 * @author marc
21 * @version $Id:$
22 */
Marc Slemko740343d2006-07-20 00:31:02 +000023class ThreadManagerTests {
24
25public:
26
Marc Slemko6f038a72006-08-03 18:58:09 +000027 static const double ERROR;
28
Marc Slemko740343d2006-07-20 00:31:02 +000029 class Task: public Runnable {
30
31 public:
32
33 Task(Monitor& monitor, size_t& count, long long timeout) :
34 _monitor(monitor),
35 _count(count),
36 _timeout(timeout),
Marc Slemko740343d2006-07-20 00:31:02 +000037 _done(false) {}
38
39 void run() {
40
Marc Slemkoc7782972006-07-25 02:26:35 +000041 _startTime = Util::currentTime();
Marc Slemko740343d2006-07-20 00:31:02 +000042
Mark Sleef5f2be42006-09-05 21:05:31 +000043 {
44 Synchronized s(_sleep);
Marc Slemko740343d2006-07-20 00:31:02 +000045
Marc Slemkoc7782972006-07-25 02:26:35 +000046 _sleep.wait(_timeout);
Marc Slemkofe5ba12e2006-07-20 21:16:27 +000047 }
Marc Slemko740343d2006-07-20 00:31:02 +000048
Marc Slemkoc7782972006-07-25 02:26:35 +000049 _endTime = Util::currentTime();
50
Marc Slemko740343d2006-07-20 00:31:02 +000051 _done = true;
52
Mark Sleef5f2be42006-09-05 21:05:31 +000053 {
54 Synchronized s(_monitor);
Marc Slemko740343d2006-07-20 00:31:02 +000055
56 // std::cout << "Thread " << _count << " completed " << std::endl;
57
58 _count--;
59
Mark Sleef5f2be42006-09-05 21:05:31 +000060 if (_count == 0) {
Marc Slemko740343d2006-07-20 00:31:02 +000061
62 _monitor.notify();
63 }
64 }
65 }
66
67 Monitor& _monitor;
68 size_t& _count;
69 long long _timeout;
Marc Slemkoc7782972006-07-25 02:26:35 +000070 long long _startTime;
71 long long _endTime;
Marc Slemko740343d2006-07-20 00:31:02 +000072 bool _done;
Marc Slemkoc7782972006-07-25 02:26:35 +000073 Monitor _sleep;
Marc Slemko740343d2006-07-20 00:31:02 +000074 };
75
Mark Sleef5f2be42006-09-05 21:05:31 +000076 /**
77 * Dispatch count tasks, each of which blocks for timeout milliseconds then
78 * completes. Verify that all tasks completed and that thread manager cleans
79 * up properly on delete.
80 */
Marc Slemkofe5ba12e2006-07-20 21:16:27 +000081 bool loadTest(size_t count=100, long long timeout=100LL, size_t workerCount=4) {
Marc Slemko740343d2006-07-20 00:31:02 +000082
83 Monitor monitor;
84
85 size_t activeCount = count;
86
Marc Slemko6f038a72006-08-03 18:58:09 +000087 shared_ptr<ThreadManager> threadManager = ThreadManager::newSimpleThreadManager(workerCount);
Marc Slemkoc7782972006-07-25 02:26:35 +000088
Marc Slemko6f038a72006-08-03 18:58:09 +000089 shared_ptr<PosixThreadFactory> threadFactory = shared_ptr<PosixThreadFactory>(new PosixThreadFactory());
Marc Slemkoc7782972006-07-25 02:26:35 +000090
91 threadFactory->priority(PosixThreadFactory::HIGHEST);
Marc Slemko740343d2006-07-20 00:31:02 +000092
Marc Slemkoc7782972006-07-25 02:26:35 +000093 threadManager->threadFactory(threadFactory);
Marc Slemkofe5ba12e2006-07-20 21:16:27 +000094
95 threadManager->start();
Marc Slemko740343d2006-07-20 00:31:02 +000096
Marc Slemko6f038a72006-08-03 18:58:09 +000097 std::set<shared_ptr<ThreadManagerTests::Task> > tasks;
Marc Slemko740343d2006-07-20 00:31:02 +000098
Mark Sleef5f2be42006-09-05 21:05:31 +000099 for (size_t ix = 0; ix < count; ix++) {
Marc Slemko740343d2006-07-20 00:31:02 +0000100
Marc Slemko6f038a72006-08-03 18:58:09 +0000101 tasks.insert(shared_ptr<ThreadManagerTests::Task>(new ThreadManagerTests::Task(monitor, activeCount, timeout)));
Marc Slemko740343d2006-07-20 00:31:02 +0000102 }
103
Marc Slemkofe5ba12e2006-07-20 21:16:27 +0000104 long long time00 = Util::currentTime();
105
Mark Sleef5f2be42006-09-05 21:05:31 +0000106 for (std::set<shared_ptr<ThreadManagerTests::Task> >::iterator ix = tasks.begin(); ix != tasks.end(); ix++) {
Marc Slemko740343d2006-07-20 00:31:02 +0000107
108 threadManager->add(*ix);
109 }
110
Mark Sleef5f2be42006-09-05 21:05:31 +0000111 {
112 Synchronized s(monitor);
113
Marc Slemko740343d2006-07-20 00:31:02 +0000114 while(activeCount > 0) {
115
116 monitor.wait();
117 }
118 }
119
Marc Slemkofe5ba12e2006-07-20 21:16:27 +0000120 long long time01 = Util::currentTime();
Marc Slemko740343d2006-07-20 00:31:02 +0000121
Marc Slemkoc7782972006-07-25 02:26:35 +0000122 long long firstTime = 9223372036854775807LL;
123 long long lastTime = 0;
124
125 double averageTime = 0;
126 long long minTime = 9223372036854775807LL;
127 long long maxTime = 0;
128
Mark Sleef5f2be42006-09-05 21:05:31 +0000129 for (std::set<shared_ptr<ThreadManagerTests::Task> >::iterator ix = tasks.begin(); ix != tasks.end(); ix++) {
Marc Slemkoc7782972006-07-25 02:26:35 +0000130
Marc Slemko6f038a72006-08-03 18:58:09 +0000131 shared_ptr<ThreadManagerTests::Task> task = *ix;
Marc Slemkoc7782972006-07-25 02:26:35 +0000132
133 long long delta = task->_endTime - task->_startTime;
134
135 assert(delta > 0);
136
Mark Sleef5f2be42006-09-05 21:05:31 +0000137 if (task->_startTime < firstTime) {
Marc Slemkoc7782972006-07-25 02:26:35 +0000138 firstTime = task->_startTime;
139 }
140
Mark Sleef5f2be42006-09-05 21:05:31 +0000141 if (task->_endTime > lastTime) {
Marc Slemkoc7782972006-07-25 02:26:35 +0000142 lastTime = task->_endTime;
143 }
144
Mark Sleef5f2be42006-09-05 21:05:31 +0000145 if (delta < minTime) {
Marc Slemkoc7782972006-07-25 02:26:35 +0000146 minTime = delta;
147 }
148
Mark Sleef5f2be42006-09-05 21:05:31 +0000149 if (delta > maxTime) {
Marc Slemkoc7782972006-07-25 02:26:35 +0000150 maxTime = delta;
151 }
152
153 averageTime+= delta;
Marc Slemko740343d2006-07-20 00:31:02 +0000154 }
Marc Slemkoc7782972006-07-25 02:26:35 +0000155
156 averageTime /= count;
157
158 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 +0000159
Marc Slemkofe5ba12e2006-07-20 21:16:27 +0000160 double expectedTime = ((count + (workerCount - 1)) / workerCount) * timeout;
161
162 double error = ((time01 - time00) - expectedTime) / expectedTime;
163
Mark Sleef5f2be42006-09-05 21:05:31 +0000164 if (error < 0) {
Marc Slemkofe5ba12e2006-07-20 21:16:27 +0000165 error*= -1.0;
166 }
167
Marc Slemko6f038a72006-08-03 18:58:09 +0000168 bool success = error < ERROR;
Marc Slemkoc7782972006-07-25 02:26:35 +0000169
Marc Slemkofe5ba12e2006-07-20 21:16:27 +0000170 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 +0000171
Marc Slemkoc7782972006-07-25 02:26:35 +0000172 return success;
Marc Slemko740343d2006-07-20 00:31:02 +0000173 }
174};
Marc Slemko6f038a72006-08-03 18:58:09 +0000175
176const double ThreadManagerTests::ERROR = .20;
177
Marc Slemko740343d2006-07-20 00:31:02 +0000178}}}} // facebook::thrift::concurrency
179
180using namespace facebook::thrift::concurrency::test;
181