#include #include #include #include "../../../shared/MiscSupport.h" #include "../../DataFormat.h" // g++ -lpthread -O4 -std=c++0x main.C ../../../shared/MiscSupport.C ../../DataFormat.C ../../../shared/FixedMalloc.C /* Major discoveries: * o Using dynamic memory (explictly or through a string) is very slow compared * to integer operations. * o My smart Value::Ref type was not much different from a std::string in a * single threaded app. * o My FixedMalloc class has no appreciable effect in a single threaded * program. * o FixedMalloc caused huge performance issues in a multi-threaded program * with a lot of dynamic memory. * o Converting a string literal to a std::string is 5x as expensive as storing * the string as a static constant. * o Performance of dynamic memory and thread safe refcounts used by * std::string does NOT degrade when running in multiple threads. * o The optimizer does NOT automatically convert push_back(Constructor(arg)) * into emplace_back(arg). (I've seen emplace in the debugger in several * places, and I didn't have it in my source code, so I assumed the compiler * was dong that for me.) * Plans: * o Disable FixedMalloc in TSRefCount, and possibly everywhere. * o Make Value into a non-pointer type. As long as it only contains an * integer or a double, do not use dynamic memory. */ template < class T > int64_t count(int max, int loop) { if (max > std::numeric_limits< T >::max()) return -1; const int64_t start = getMicroTime(); std::vector< T > v; for (int l = 0; l < loop; l++) { v.clear(); for (int i = 0; i < max; i++) v.push_back(i); } return getMicroTime() - start; } int64_t countValue(int max, int loop) { const int64_t start = getMicroTime(); std::vector< ValueBox > v; for (int l = 0; l < loop; l++) { v.clear(); for (int i = 0; i < max; i++) v.push_back(i); } return getMicroTime() - start; } int64_t countNtoa(int max, int loop) { const int64_t start = getMicroTime(); std::vector< std::string > v; for (int l = 0; l < loop; l++) { v.clear(); for (int i = 0; i < max; i++) v.push_back(ntoa(i)); } return getMicroTime() - start; } const std::string s_FIXED = "FIXED"; int64_t countGlobalFixedString(int max, int loop) { const int64_t start = getMicroTime(); std::vector< std::string > v; for (int l = 0; l < loop; l++) { v.clear(); for (int i = 0; i < max; i++) v.push_back(s_FIXED); } return getMicroTime() - start; } int64_t countLocalFixedString(int max, int loop) { const std::string FIXED = "FIXED"; const int64_t start = getMicroTime(); std::vector< std::string > v; for (int l = 0; l < loop; l++) { v.clear(); for (int i = 0; i < max; i++) v.push_back(FIXED); } return getMicroTime() - start; } int64_t countCharStar(int max, int loop) { const int64_t start = getMicroTime(); std::vector< std::string > v; for (int l = 0; l < loop; l++) { v.clear(); for (int i = 0; i < max; i++) //v.push_back("char *"); v.emplace_back("char *"); } return getMicroTime() - start; } class NewTest { private: int _size; char *_value; public: NewTest(int value) : _size((value%10) + 10), _value(new char[_size]) { } NewTest(NewTest const &other) : _size(other._size), _value(new char[_size]) { } void operator =(NewTest const &other) { delete [] _value; _size = other._size; _value = new char[_size]; } ~NewTest() { delete [] _value; } }; int64_t countNew(int max, int loop) { const int64_t start = getMicroTime(); std::vector< NewTest > v; for (int l = 0; l < loop; l++) { v.clear(); for (int i = 0; i < max; i++) v.push_back(NewTest(i)); } return getMicroTime() - start; }; class MallocTest { private: int _size; char *_value; public: MallocTest(int value) : _size((value%10) + 10), _value((char *)malloc(_size)) { } MallocTest(MallocTest const &other) : _size(other._size), _value((char *)malloc(_size)) { } void operator =(MallocTest const &other) { free(_value); _size = other._size; _value = (char *)malloc(_size); } ~MallocTest() { free(_value); } }; int64_t countMalloc(int max, int loop) { const int64_t start = getMicroTime(); std::vector< MallocTest > v; for (int l = 0; l < loop; l++) { v.clear(); for (int i = 0; i < max; i++) //v.push_back(MallocTest(i)); // Emplace cut the time approximately in half! v.emplace_back(i); } return getMicroTime() - start; }; int64_t countRefCount(int max, int loop) { typedef RefCount< int > Type; const int64_t start = getMicroTime(); std::vector< Type > v; for (int l = 0; l < loop; l++) { v.clear(); for (int i = 0; i < max; i++) v.push_back(new int); } return getMicroTime() - start; }; int64_t countTSRefCount(int max, int loop) { typedef TSRefCount< int > Type; const int64_t start = getMicroTime(); std::vector< Type > v; for (int l = 0; l < loop; l++) { v.clear(); for (int i = 0; i < max; i++) v.push_back(new int); } return getMicroTime() - start; }; typedef TSRefCount< int > TSRCInt; const TSRCInt sharedTSRCInt = new int; int64_t countSharedTSRefCount(int max, int loop) { const int64_t start = getMicroTime(); std::vector< TSRCInt > v; for (int l = 0; l < loop; l++) { v.clear(); for (int i = 0; i < max; i++) v.push_back(sharedTSRCInt); } return getMicroTime() - start; }; int64_t countReusedTSRefCount(int max, int loop) { const TSRCInt reused = new int; const int64_t start = getMicroTime(); std::vector< TSRCInt > v; for (int l = 0; l < loop; l++) { v.clear(); for (int i = 0; i < max; i++) v.push_back(sharedTSRCInt); } return getMicroTime() - start; }; pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; void countAll(int max, int loop) { const int64_t t14 = countSharedTSRefCount(max, loop); const int64_t t15 = countReusedTSRefCount(max, loop); const int64_t t1 = count< unsigned char >(max, loop); const int64_t t2 = count< int16_t >(max, loop); const int64_t t3 = count< int >(max, loop); const int64_t t4 = count< int64_t >(max, loop); const int64_t t5 = countValue(max, loop); const int64_t t6 = countNtoa(max, loop); const int64_t t7 = countGlobalFixedString(max, loop); const int64_t t8 = countLocalFixedString(max, loop); const int64_t t9 = countCharStar(max, loop); const int64_t t10 = countNew(max, loop); const int64_t t11 = countMalloc(max, loop); const int64_t t12 = countRefCount(max, loop); const int64_t t13 = countTSRefCount(max, loop); pthread_mutex_lock(&mutex); std::cout<<"unsigned char: "< std::string: "< std::string: "< threads; while (threadCount--) { pthread_t thread; pthread_create(&thread, NULL, threadFunction, NULL); threads.push_back(thread); } void *threadResult; for (auto it = threads.cbegin(); it != threads.cend(); it++) pthread_join(*it, &threadResult); }