//: C04:SequencePerformance.cpp // From Thinking in C++, 2nd Edition // Available at http://www.BruceEckel.com // (c) Bruce Eckel 2000 // Copyright notice in Copyright.txt // Comparing the performance of the basic // sequence containers for various operations #include #include #include #include #include #include #include #include using namespace std; class FixedSize { int x[20]; // Automatic generation of default constructor, // copy-constructor and operator= } fs; template struct InsertBack { void operator()(Cont& c, long count) { for(long i = 0; i < count; i++) c.push_back(fs); } char* testName() { return "InsertBack"; } }; template struct InsertFront { void operator()(Cont& c, long count) { long cnt = count * 10; for(long i = 0; i < cnt; i++) c.push_front(fs); } char* testName() { return "InsertFront"; } }; template struct InsertMiddle { void operator()(Cont& c, long count) { typename Cont::iterator it; long cnt = count / 10; for(long i = 0; i < cnt; i++) { // Must get the iterator every time to keep // from causing an access violation with // vector. Increment it to put it in the // middle of the container: it = c.begin(); it++; c.insert(it, fs); } } char* testName() { return "InsertMiddle"; } }; template struct RandomAccess { // Not for list void operator()(Cont& c, long count) { int sz = c.size(); long cnt = count * 100; for(long i = 0; i < cnt; i++) c[rand() % sz]; } char* testName() { return "RandomAccess"; } }; template struct Traversal { void operator()(Cont& c, long count) { long cnt = count / 100; for(long i = 0; i < cnt; i++) { typename Cont::iterator it = c.begin(), end = c.end(); while(it != end) it++; } } char* testName() { return "Traversal"; } }; template struct Swap { void operator()(Cont& c, long count) { int middle = c.size() / 2; typename Cont::iterator it = c.begin(), mid = c.begin(); it++; // Put it in the middle for(int x = 0; x < middle + 1; x++) mid++; long cnt = count * 10; for(long i = 0; i < cnt; i++) swap(*it, *mid); } char* testName() { return "Swap"; } }; template struct RemoveMiddle { void operator()(Cont& c, long count) { long cnt = count / 10; if(cnt > c.size()) { cout << "RemoveMiddle: not enough elements" << endl; return; } for(long i = 0; i < cnt; i++) { typename Cont::iterator it = c.begin(); it++; c.erase(it); } } char* testName() { return "RemoveMiddle"; } }; template struct RemoveBack { void operator()(Cont& c, long count) { long cnt = count * 10; if(cnt > c.size()) { cout << "RemoveBack: not enough elements" << endl; return; } for(long i = 0; i < cnt; i++) c.pop_back(); } char* testName() { return "RemoveBack"; } }; template void measureTime(Op f, Container& c, long count){ string id(typeid(f).name()); bool Deque = id.find("deque") != string::npos; bool List = id.find("list") != string::npos; bool Vector = id.find("vector") !=string::npos; string cont = Deque ? "deque" : List ? "list" : Vector? "vector" : "unknown"; cout << f.testName() << " for " << cont << ": "; // Standard C library CPU ticks: clock_t ticks = clock(); f(c, count); // Run the test ticks = clock() - ticks; cout << ticks << endl; } typedef deque DF; typedef list LF; typedef vector VF; int main(int argc, char* argv[]) { srand(time(0)); long count = 1000; if(argc >= 2) count = atoi(argv[1]); DF deq; LF lst; VF vec, vecres; vecres.reserve(count); // Preallocate storage measureTime(InsertBack(), vec, count); measureTime(InsertBack(), vecres, count); measureTime(InsertBack(), deq, count); measureTime(InsertBack(), lst, count); // Can't push_front() with a vector: //! measureTime(InsertFront(), vec, count); measureTime(InsertFront(), deq, count); measureTime(InsertFront(), lst, count); measureTime(InsertMiddle(), vec, count); measureTime(InsertMiddle(), deq, count); measureTime(InsertMiddle(), lst, count); measureTime(RandomAccess(), vec, count); measureTime(RandomAccess(), deq, count); // Can't operator[] with a list: //! measureTime(RandomAccess(), lst, count); measureTime(Traversal(), vec, count); measureTime(Traversal(), deq, count); measureTime(Traversal(), lst, count); measureTime(Swap(), vec, count); measureTime(Swap(), deq, count); measureTime(Swap(), lst, count); measureTime(RemoveMiddle(), vec, count); measureTime(RemoveMiddle(), deq, count); measureTime(RemoveMiddle(), lst, count); vec.resize(vec.size() * 10); // Make it bigger measureTime(RemoveBack(), vec, count); measureTime(RemoveBack(), deq, count); measureTime(RemoveBack(), lst, count); } ///:~