From: Marc Slemko Date: Tue, 25 Jul 2006 02:26:35 +0000 (+0000) Subject: autoconf/automake/libtool-ized thrift cpp bits: X-Git-Tag: 0.2.0~1739 X-Git-Url: https://source.supwisdom.com/gerrit/gitweb?a=commitdiff_plain;h=c778297bd0e4f468967df59555c2d3dcaf4fc6cb;p=common%2Fthrift.git autoconf/automake/libtool-ized thrift cpp bits: Fixed to build on solaris. Used clock_gettime() where available Fixed rounding of time to ms git-svn-id: https://svn.apache.org/repos/asf/incubator/thrift/trunk@664733 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/lib/cpp/configure.ac b/lib/cpp/configure.ac index a269df6c..77a4f328 100644 --- a/lib/cpp/configure.ac +++ b/lib/cpp/configure.ac @@ -34,6 +34,10 @@ AC_CHECK_HEADERS([unistd.h]) AC_CHECK_LIB(pthread, pthread_create) +AC_CHECK_LIB(rt, sched_get_priority_min) + +AC_CHECK_FUNCS([clock_gettime]) + AC_C_CONST AC_C_VOLATILE diff --git a/lib/cpp/src/concurrency/Util.h b/lib/cpp/src/concurrency/Util.h index 8467a2cb..6e8891db 100644 --- a/lib/cpp/src/concurrency/Util.h +++ b/lib/cpp/src/concurrency/Util.h @@ -1,6 +1,8 @@ #if !defined(_concurrency_Util_h_) #define _concurrency_Util_h_ 1 +#include + #include #include #include @@ -18,6 +20,12 @@ namespace facebook { namespace thrift { namespace concurrency { class Util { + static const long long NS_PER_S = 1000000000LL; + + static const long long MS_PER_S = 1000LL; + + static const long long NS_PER_MS = 1000000LL; + public: /** Converts timespec to milliseconds @@ -26,28 +34,39 @@ class Util { @param time or duration in milliseconds */ static void toTimespec(struct timespec& result, long long value) { + + result.tv_sec = value / MS_PER_S; // ms to s - result.tv_sec = value / 1000; // ms to s - - result.tv_nsec = (value % 1000) * 1000000; // ms to ns + result.tv_nsec = (value % MS_PER_S) * NS_PER_MS; // ms to ns } /** Converts timespec to milliseconds */ static const void toMilliseconds(long long& result, const struct timespec& value) { - result = value.tv_sec * 1000 + value.tv_nsec / 1000000; + result = (value.tv_sec * MS_PER_S) + (value.tv_nsec / NS_PER_MS) + (value.tv_nsec % NS_PER_MS >= 500000 ? 1 : 0) ; } /** Get current time as milliseconds from epoch */ static const long long currentTime() { +#if defined(HAVE_CLOCK_GETTIME) + + struct timespec now; + + assert(clock_gettime(&now, NULL) == 0); + + return = (now.tv_sec * MS_PER_S) + (now.tv_nsec / NS_PER_MS) + (now.tv_nsec % NS_PER_MS >= 500000 ? 1 : 0) ; + +#elif defined(HAVE_GETTIMEOFDAY) + struct timeval now; assert(gettimeofday(&now, NULL) == 0); - return ((long long)now.tv_sec) * 1000LL + now.tv_usec / 1000; + return (((long long)now.tv_sec) * MS_PER_S) + (now.tv_usec / MS_PER_S) + (now.tv_usec % MS_PER_S >= 500 ? 1 : 0); +#endif // defined(HAVE_GETTIMEDAY) } }; diff --git a/lib/cpp/src/concurrency/test/Tests.cc b/lib/cpp/src/concurrency/test/Tests.cc index 19e1f4a6..5c4dd242 100644 --- a/lib/cpp/src/concurrency/test/Tests.cc +++ b/lib/cpp/src/concurrency/test/Tests.cc @@ -1,4 +1,5 @@ #include +#include #include #include "ThreadFactoryTests.h" @@ -9,27 +10,22 @@ int main(int argc, char** argv) { std::string arg; - if(argc < 2) { + std::vector args(argc - 1 > 1 ? argc - 1 : 1); - arg = "all"; + args[0] = "all"; - } else { - - arg = std::string(argv[1]); + for(int ix = 1; ix < argc; ix++) { + args[ix - 1] = std::string(argv[ix]); } - bool runAll = arg.compare("all") == 0; + bool runAll = args[0].compare("all") == 0; - if(runAll || arg.compare("thread-factory") == 0) { + if(runAll || args[0].compare("thread-factory") == 0) { ThreadFactoryTests threadFactoryTests; std::cout << "ThreadFactory tests..." << std::endl; - std::cout << "\tThreadFactory hello-world test" << std::endl; - - assert(threadFactoryTests.helloWorldTest()); - size_t count = 1000; std::cout << "\t\tThreadFactory reap N threads test: N = " << count << std::endl; @@ -39,9 +35,37 @@ int main(int argc, char** argv) { std::cout << "\t\tThreadFactory synchronous start test" << std::endl; assert(threadFactoryTests.synchStartTest()); + + std::cout << "\t\tThreadFactory monitor timeout test" << std::endl; + + assert(threadFactoryTests.monitorTimeoutTest()); } - if(runAll || arg.compare("timer-manager") == 0) { + if(runAll || args[0].compare("util") == 0) { + + std::cout << "Util tests..." << std::endl; + + std::cout << "\t\tUtil minimum time" << std::endl; + + long long time00 = Util::currentTime(); + long long time01 = Util::currentTime(); + + std::cout << "\t\t\tMinimum time: " << time01 - time00 << "ms" << std::endl; + + time00 = Util::currentTime(); + time01 = time00; + size_t count = 0; + + while(time01 < time00 + 10) { + count++; + time01 = Util::currentTime(); + } + + std::cout << "\t\t\tscall per ms: " << count / (time01 - time00) << std::endl; + } + + + if(runAll || args[0].compare("timer-manager") == 0) { std::cout << "TimerManager tests..." << std::endl; @@ -52,21 +76,51 @@ int main(int argc, char** argv) { assert(timerManagerTests.test00()); } - if(runAll || arg.compare("thread-manager") == 0) { + if(runAll || args[0].compare("thread-manager") == 0) { std::cout << "ThreadManager tests..." << std::endl; - size_t workerCount = 100; + { + + size_t workerCount = 100; + + size_t taskCount = 100000; + + long long delay = 10LL; + + std::cout << "\t\tThreadManager load test: worker count: " << workerCount << " task count: " << taskCount << " delay: " << delay << std::endl; + + ThreadManagerTests threadManagerTests; + + assert(threadManagerTests.loadTest(taskCount, delay, workerCount)); + } + } + + if(runAll || args[0].compare("thread-manager-benchmark") == 0) { + + std::cout << "ThreadManager benchmark tests..." << std::endl; + + { + + size_t minWorkerCount = 2; + + size_t maxWorkerCount = 512; + + size_t tasksPerWorker = 1000; + + long long delay = 10LL; - size_t taskCount = 100000; + for(size_t workerCount = minWorkerCount; workerCount < maxWorkerCount; workerCount*= 2) { - long long delay = 10LL; + size_t taskCount = workerCount * tasksPerWorker; - std::cout << "\t\tThreadManager load test: worker count: " << workerCount << " task count: " << taskCount << " delay: " << delay << std::endl; + std::cout << "\t\tThreadManager load test: worker count: " << workerCount << " task count: " << taskCount << " delay: " << delay << std::endl; - ThreadManagerTests threadManagerTests; + ThreadManagerTests threadManagerTests; - assert(threadManagerTests.loadTest(taskCount, delay, workerCount)); + threadManagerTests.loadTest(taskCount, delay, workerCount); + } + } } } diff --git a/lib/cpp/src/concurrency/test/ThreadFactoryTests.h b/lib/cpp/src/concurrency/test/ThreadFactoryTests.h index 1e0b1393..d1ec0df0 100644 --- a/lib/cpp/src/concurrency/test/ThreadFactoryTests.h +++ b/lib/cpp/src/concurrency/test/ThreadFactoryTests.h @@ -1,6 +1,7 @@ #include #include #include +#include #include #include @@ -216,9 +217,42 @@ public: assert(state == SynchStartTask::STOPPED); + bool success = true; + + std::cout << "\t\t\t" << (success ? "Success" : "Failure") << "!" << std::endl; + return true; } + /** See how accurate monitor timeout is. */ + + bool monitorTimeoutTest(size_t count=1000, long long timeout=10) { + + Monitor monitor; + + long long startTime = Util::currentTime(); + + for(size_t ix = 0; ix < count; ix++) { + {Synchronized s(monitor); + monitor.wait(timeout); + } + } + + long long endTime = Util::currentTime(); + + double error = ((endTime - startTime) - (count * timeout)) / (double)(count * timeout); + + if(error < 0.0) { + + error *= 1.0; + } + + bool success = error < .10; + + std::cout << "\t\t\t" << (success ? "Success" : "Failure") << "! expected time: " << count * timeout << "ms elapsed time: "<< endTime - startTime << "ms error%: " << error * 100.0 << std::endl; + + return success; + } }; diff --git a/lib/cpp/src/concurrency/test/ThreadManagerTests.h b/lib/cpp/src/concurrency/test/ThreadManagerTests.h index 61325717..8b2dda8b 100644 --- a/lib/cpp/src/concurrency/test/ThreadManagerTests.h +++ b/lib/cpp/src/concurrency/test/ThreadManagerTests.h @@ -1,3 +1,4 @@ +#include #include #include #include @@ -6,6 +7,8 @@ #include #include #include +#include +#include namespace facebook { namespace thrift { namespace concurrency { namespace test { @@ -32,29 +35,16 @@ public: void run() { - Monitor sleep; - - {Synchronized s(sleep); - - long long time00 = Util::currentTime(); - - sleep.wait(_timeout); + _startTime = Util::currentTime(); - long long time01 = Util::currentTime(); + {Synchronized s(_sleep); - double error = ((time01 - time00) - _timeout) / (double)_timeout; - - if(error < 0.0) { - - error*= -1.0; - } - if(error > .20) { - - assert(false); - } + _sleep.wait(_timeout); } + _endTime = Util::currentTime(); + _done = true; {Synchronized s(_monitor); @@ -73,7 +63,10 @@ public: Monitor& _monitor; size_t& _count; long long _timeout; + long long _startTime; + long long _endTime; bool _done; + Monitor _sleep; }; /** Dispatch count tasks, each of which blocks for timeout milliseconds then completes. @@ -86,8 +79,12 @@ public: size_t activeCount = count; ThreadManager* threadManager = ThreadManager::newSimpleThreadManager(workerCount); + + PosixThreadFactory* threadFactory = new PosixThreadFactory(); + + threadFactory->priority(PosixThreadFactory::HIGHEST); - threadManager->threadFactory(new PosixThreadFactory()); + threadManager->threadFactory(threadFactory); threadManager->start(); @@ -115,11 +112,45 @@ public: long long time01 = Util::currentTime(); + long long firstTime = 9223372036854775807LL; + long long lastTime = 0; + + double averageTime = 0; + long long minTime = 9223372036854775807LL; + long long maxTime = 0; + for(std::set::iterator ix = tasks.begin(); ix != tasks.end(); ix++) { + + ThreadManagerTests::Task* task = *ix; + + long long delta = task->_endTime - task->_startTime; + + assert(delta > 0); + + if(task->_startTime < firstTime) { + firstTime = task->_startTime; + } + + if(task->_endTime > lastTime) { + lastTime = task->_endTime; + } + + if(delta < minTime) { + minTime = delta; + } + + if(delta > maxTime) { + maxTime = delta; + } + + averageTime+= delta; delete *ix; - } + + averageTime /= count; + + std::cout << "\t\t\tfirst start: " << firstTime << "ms Last end: " << lastTime << "ms min: " << minTime << "ms max: " << maxTime << "ms average: " << averageTime << "ms" << std::endl; double expectedTime = ((count + (workerCount - 1)) / workerCount) * timeout; @@ -133,9 +164,11 @@ public: delete threadManager; + delete threadFactory; + std::cout << "\t\t\t" << (success ? "Success" : "Failure") << "! expected time: " << expectedTime << "ms elapsed time: "<< time01 - time00 << "ms error%: " << error * 100.0 << std::endl; - return true; + return success; } };