1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 | /* From @waleri, suggestions of Article improvement by adding a test to discover how much memory allocations drag-down the linked-list (LL). LL does memory allocations for every node, compared to vector that does it in chunks. Comparison 1: Compare LL pre-allocated vs LL non-allocated for random insertions. Article question: "Another test you can do" http://www.codeproject.com/Articles/340797/Number-crunching-Why-you-should-never-ever-EVER-us?msg=4253843#xx4253843xx*/ #include <list> #include <vector> #include <iostream> #include <iomanip> #include <functional> #include <random> #include <iostream> #include <chrono> #include <string> #include <numeric> #include <algorithm> #include <cassert> namespace g2 { typedef std::chrono::high_resolution_clock clock; typedef std::chrono::microseconds microseconds; typedef std::chrono::milliseconds milliseconds; clock::time_point now(){return clock::now();} microseconds intervalUs(const clock::time_point& t1, const clock::time_point& t0) {return std::chrono::duration_cast<microseconds>(t1 - t0);} milliseconds intervalMs(const clock::time_point& t1,const clock::time_point& t0) {return std::chrono::duration_cast<milliseconds>(t1 - t0);} class StopWatch { clock::time_point start_; public: StopWatch() : start_(clock::now()){} clock::time_point restart() { start_ = clock::now(); return start_;} microseconds elapsedUs() { return intervalUs(now(), start_);} milliseconds elapsedMs() {return intervalMs(now(), start_);} }; } // g2 typedef unsigned int Number; typedef std::list<Number> NumbersInList; typedef std::vector<Number> NumbersInVector; typedef long long int TimeValue; int random_int(int low, int high) { using namespace std; static default_random_engine engine; typedef uniform_int_distribution<int> Distribution; static Distribution distribution; return distribution(engine, Distribution::param_type(low, high)); } // Measure time in milliseconds for linear insert in a std container template<typename Container> TimeValue linearInsertPerformance(const NumbersInVector& randoms, Container& container) { g2::StopWatch watch; { std::for_each(randoms.begin(), randoms.end(), [&](const Number& n) { auto itr = container.begin(); for (; itr!= container.end(); ++itr) { if ((*itr) >= n) { break; } } container.insert(itr, n); }); } auto time = watch.elapsedUs().count(); return time; } // Measure time in milliseconds for linear insert in a std container template<typename Container> TimeValue linearInsertPerformance(const NumbersInVector& randoms, Container& memory_pool_container, Container& container) { g2::StopWatch watch; { std::for_each(randoms.begin(), randoms.end(), [&](const Number& n) { auto itr = container.begin(); for (; itr!= container.end(); ++itr) { if ((*itr) >= n) { break; } } auto pool_itr = memory_pool_container.begin(); (*pool_itr) = n; // set the random value container.splice(itr, memory_pool_container, pool_itr); // insert value from the pool }); } auto time = watch.elapsedUs().count(); return time; } // Used for debugging and verification, // normally disabled template<typename Container> void printValues(const std::string& msg, const Container& values) { std::cout << msg << std::endl; std::for_each(values.begin(), values.end(), [&](const Number& n) { std::cout << " " << n << " "; }); std::cout << "\n" << std::endl; } void linked_listPerformance(size_t nbr_of_randoms) { // Generate n random values and push to storage NumbersInVector values(nbr_of_randoms); std::for_each(values.begin(), values.end(), [&](Number& n) { n = random_int(0, nbr_of_randoms -1);}); TimeValue list_time; TimeValue vector_time; TimeValue list_time_preallocated; { // LL NumbersInList list; list_time = linearInsertPerformance(values, list); } { // Vector NumbersInVector vector; vector_time = linearInsertPerformance(values, vector); } { // LL - PreAllocated NumbersInList memory_pool(nbr_of_randoms, -1); // pre-allocated LL used as memory pool NumbersInList list_preallocated; list_time_preallocated = linearInsertPerformance(values, memory_pool, list_preallocated); } std::cout << nbr_of_randoms << ", " << std::flush; std::cout << list_time << ", " << list_time_preallocated << ", " << vector_time << std::endl << std::flush; } int main(int argc, char** argv) { std::cout << "Pre-allocated linked-list vs linked-list" << std::endl; std::cout << "This shows how much time is actually used for memory allocations in" << std::endl; std::cout << "perspective with cost for traversing. Both lists are in disjoint memory!" << std::endl; std::cout << "\n#items, LL (us), LL pre-allocated (us) , vector (us) " << std::endl; g2::StopWatch watch; linked_listPerformance(10); linked_listPerformance(100); linked_listPerformance(500); linked_listPerformance(1000); linked_listPerformance(2000); linked_listPerformance(10000); linked_listPerformance(20000); linked_listPerformance(40000); linked_listPerformance(100000); linked_listPerformance(500000); linked_listPerformance(1000000); auto total_time_ms = watch.elapsedMs().count(); std::cout << "Exiting test,. the whole measuring took " << total_time_ms << " milliseconds"; std::cout << " (" << total_time_ms/1000 << "seconds or " << total_time_ms/(1000*60) << " minutes)" << std::endl; return 0; } |
LyogRnJvbSBAd2FsZXJpLCBzdWdnZXN0aW9ucyBvZiBBcnRpY2xlIGltcHJvdmVtZW50IGJ5IGFkZGluZyBhIHRlc3QgdG8gZGlzY292ZXIgaG93IG11Y2ggbWVtb3J5IGFsbG9jYXRpb25zIGRyYWctZG93biB0aGUgbGlua2VkLWxpc3QgKExMKS4gTEwgZG9lcyBtZW1vcnkgYWxsb2NhdGlvbnMgZm9yIGV2ZXJ5IG5vZGUsIGNvbXBhcmVkIHRvIHZlY3RvciB0aGF0IGRvZXMgaXQgaW4gY2h1bmtzLiAKCkNvbXBhcmlzb24gMTogQ29tcGFyZSBMTCBwcmUtYWxsb2NhdGVkIHZzIExMIG5vbi1hbGxvY2F0ZWQgZm9yIHJhbmRvbSBpbnNlcnRpb25zLgoKQXJ0aWNsZSBxdWVzdGlvbjogIkFub3RoZXIgdGVzdCB5b3UgY2FuIGRvIgpodHRwOi8vd3d3LmNvZGVwcm9qZWN0LmNvbS9BcnRpY2xlcy8zNDA3OTcvTnVtYmVyLWNydW5jaGluZy1XaHkteW91LXNob3VsZC1uZXZlci1ldmVyLUVWRVItdXM/bXNnPTQyNTM4NDMjeHg0MjUzODQzeHgqLwoKI2luY2x1ZGUgPGxpc3Q+CiNpbmNsdWRlIDx2ZWN0b3I+CiNpbmNsdWRlIDxpb3N0cmVhbT4KI2luY2x1ZGUgPGlvbWFuaXA+CiNpbmNsdWRlIDxmdW5jdGlvbmFsPgojaW5jbHVkZSA8cmFuZG9tPgojaW5jbHVkZSA8aW9zdHJlYW0+CiNpbmNsdWRlIDxjaHJvbm8+CiNpbmNsdWRlIDxzdHJpbmc+CiNpbmNsdWRlIDxudW1lcmljPgojaW5jbHVkZSA8YWxnb3JpdGhtPgojaW5jbHVkZSA8Y2Fzc2VydD4KCm5hbWVzcGFjZSBnMgp7ICAgICAgIAogIHR5cGVkZWYgc3RkOjpjaHJvbm86OmhpZ2hfcmVzb2x1dGlvbl9jbG9jayBjbG9jazsKICB0eXBlZGVmIHN0ZDo6Y2hyb25vOjptaWNyb3NlY29uZHMgbWljcm9zZWNvbmRzOwogIHR5cGVkZWYgc3RkOjpjaHJvbm86Om1pbGxpc2Vjb25kcyBtaWxsaXNlY29uZHM7CgogIGNsb2NrOjp0aW1lX3BvaW50IG5vdygpe3JldHVybiBjbG9jazo6bm93KCk7fQoKICBtaWNyb3NlY29uZHMgaW50ZXJ2YWxVcyhjb25zdCBjbG9jazo6dGltZV9wb2ludCYgdDEsIGNvbnN0IGNsb2NrOjp0aW1lX3BvaW50JiB0MCkKICB7cmV0dXJuIHN0ZDo6Y2hyb25vOjpkdXJhdGlvbl9jYXN0PG1pY3Jvc2Vjb25kcz4odDEgLSB0MCk7fQoKICBtaWxsaXNlY29uZHMgaW50ZXJ2YWxNcyhjb25zdCBjbG9jazo6dGltZV9wb2ludCYgdDEsY29uc3QgY2xvY2s6OnRpbWVfcG9pbnQmIHQwKQogIHtyZXR1cm4gc3RkOjpjaHJvbm86OmR1cmF0aW9uX2Nhc3Q8bWlsbGlzZWNvbmRzPih0MSAtIHQwKTt9CgoKICBjbGFzcyBTdG9wV2F0Y2gKICB7CiAgICBjbG9jazo6dGltZV9wb2ludCBzdGFydF87CiAgcHVibGljOgogICAgU3RvcFdhdGNoKCkgOiBzdGFydF8oY2xvY2s6Om5vdygpKXt9CiAgICBjbG9jazo6dGltZV9wb2ludCByZXN0YXJ0KCkgICAgICAgICB7IHN0YXJ0XyA9IGNsb2NrOjpub3coKTsgcmV0dXJuIHN0YXJ0Xzt9CiAgICBtaWNyb3NlY29uZHMgZWxhcHNlZFVzKCkgICAgICAgICAgICB7IHJldHVybiBpbnRlcnZhbFVzKG5vdygpLCBzdGFydF8pO30KICAgIG1pbGxpc2Vjb25kcyBlbGFwc2VkTXMoKSAgICAgICAgICAgIHtyZXR1cm4gaW50ZXJ2YWxNcyhub3coKSwgc3RhcnRfKTt9CiAgfTsKfSAvLyBnMgoKCnR5cGVkZWYgdW5zaWduZWQgaW50ICBOdW1iZXI7CnR5cGVkZWYgc3RkOjpsaXN0PE51bWJlcj4gICAgICAgICAgIE51bWJlcnNJbkxpc3Q7CnR5cGVkZWYgc3RkOjp2ZWN0b3I8TnVtYmVyPiAgICAgICAgIE51bWJlcnNJblZlY3RvcjsKdHlwZWRlZiBsb25nIGxvbmcgaW50ICAgICAgICAgICAgICAgVGltZVZhbHVlOwoKCmludCByYW5kb21faW50KGludCBsb3csIGludCBoaWdoKQp7CiAgdXNpbmcgbmFtZXNwYWNlIHN0ZDsKICBzdGF0aWMgZGVmYXVsdF9yYW5kb21fZW5naW5lIGVuZ2luZTsKICB0eXBlZGVmIHVuaWZvcm1faW50X2Rpc3RyaWJ1dGlvbjxpbnQ+IERpc3RyaWJ1dGlvbjsKICBzdGF0aWMgRGlzdHJpYnV0aW9uIGRpc3RyaWJ1dGlvbjsKICByZXR1cm4gZGlzdHJpYnV0aW9uKGVuZ2luZSwgRGlzdHJpYnV0aW9uOjpwYXJhbV90eXBlKGxvdywgaGlnaCkpOwp9CgoKLy8gTWVhc3VyZSB0aW1lIGluIG1pbGxpc2Vjb25kcyBmb3IgbGluZWFyIGluc2VydCBpbiBhIHN0ZCBjb250YWluZXIKdGVtcGxhdGU8dHlwZW5hbWUgQ29udGFpbmVyPgpUaW1lVmFsdWUgbGluZWFySW5zZXJ0UGVyZm9ybWFuY2UoY29uc3QgTnVtYmVyc0luVmVjdG9yJiByYW5kb21zLCBDb250YWluZXImIGNvbnRhaW5lcikKewogICAgZzI6OlN0b3BXYXRjaCB3YXRjaDsKICAgIHsKICAgICAgIHN0ZDo6Zm9yX2VhY2gocmFuZG9tcy5iZWdpbigpLCByYW5kb21zLmVuZCgpLCBbJl0oY29uc3QgTnVtYmVyJiBuKQogICAgICAgewogICAgICAgICBhdXRvIGl0ciA9IGNvbnRhaW5lci5iZWdpbigpOwogICAgICAgICBmb3IgKDsgaXRyIT0gY29udGFpbmVyLmVuZCgpOyArK2l0cikKICAgICAgICAgewogICAgICAgICAgICBpZiAoKCppdHIpID49IG4pCiAgICAgICAgICAgIHsgIGJyZWFrOyB9CiAgICAgICAgfQogICAgICAgIGNvbnRhaW5lci5pbnNlcnQoaXRyLCBuKTsKICAgIH0pOwogICAgfQogICAgYXV0byB0aW1lID0gd2F0Y2guZWxhcHNlZFVzKCkuY291bnQoKTsKICAgIHJldHVybiB0aW1lOwp9CgovLyBNZWFzdXJlIHRpbWUgaW4gbWlsbGlzZWNvbmRzIGZvciBsaW5lYXIgaW5zZXJ0IGluIGEgc3RkIGNvbnRhaW5lcgp0ZW1wbGF0ZTx0eXBlbmFtZSBDb250YWluZXI+ClRpbWVWYWx1ZSBsaW5lYXJJbnNlcnRQZXJmb3JtYW5jZShjb25zdCBOdW1iZXJzSW5WZWN0b3ImIHJhbmRvbXMsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQ29udGFpbmVyJiBtZW1vcnlfcG9vbF9jb250YWluZXIsICBDb250YWluZXImIGNvbnRhaW5lcikKewogICAgZzI6OlN0b3BXYXRjaCB3YXRjaDsKICAgIHsKICAgICAgIHN0ZDo6Zm9yX2VhY2gocmFuZG9tcy5iZWdpbigpLCByYW5kb21zLmVuZCgpLCBbJl0oY29uc3QgTnVtYmVyJiBuKQogICAgICAgewogICAgICAgICBhdXRvIGl0ciA9IGNvbnRhaW5lci5iZWdpbigpOwogICAgICAgICBmb3IgKDsgaXRyIT0gY29udGFpbmVyLmVuZCgpOyArK2l0cikKICAgICAgICAgewogICAgICAgICAgICBpZiAoKCppdHIpID49IG4pCiAgICAgICAgICAgIHsgIGJyZWFrOyB9CiAgICAgICAgfQogICAgICAgIGF1dG8gcG9vbF9pdHIgPSBtZW1vcnlfcG9vbF9jb250YWluZXIuYmVnaW4oKTsKICAgICAgICAoKnBvb2xfaXRyKSA9IG47IC8vIHNldCB0aGUgcmFuZG9tIHZhbHVlCiAgICAgICAgY29udGFpbmVyLnNwbGljZShpdHIsIG1lbW9yeV9wb29sX2NvbnRhaW5lciwgcG9vbF9pdHIpOyAvLyBpbnNlcnQgdmFsdWUgZnJvbSB0aGUgcG9vbAogICAgfSk7CiAgICB9CiAgICBhdXRvIHRpbWUgPSB3YXRjaC5lbGFwc2VkVXMoKS5jb3VudCgpOwogICAgcmV0dXJuIHRpbWU7Cn0KCi8vIFVzZWQgZm9yIGRlYnVnZ2luZyBhbmQgdmVyaWZpY2F0aW9uLCAKLy8gbm9ybWFsbHkgZGlzYWJsZWQKdGVtcGxhdGU8dHlwZW5hbWUgQ29udGFpbmVyPgp2b2lkIHByaW50VmFsdWVzKGNvbnN0IHN0ZDo6c3RyaW5nJiBtc2csIGNvbnN0IENvbnRhaW5lciYgdmFsdWVzKQp7CiAgc3RkOjpjb3V0IDw8IG1zZyA8PCBzdGQ6OmVuZGw7CiAgc3RkOjpmb3JfZWFjaCh2YWx1ZXMuYmVnaW4oKSwgdmFsdWVzLmVuZCgpLAogICAgWyZdKGNvbnN0IE51bWJlciYgbikgeyBzdGQ6OmNvdXQgPDwgIiAiIDw8IG4gPDwgIiAiOyB9KTsgCiAKICBzdGQ6OmNvdXQgPDwgIlxuIiA8PCBzdGQ6OmVuZGw7Cn0KCgoKdm9pZCBsaW5rZWRfbGlzdFBlcmZvcm1hbmNlKHNpemVfdCBuYnJfb2ZfcmFuZG9tcykKewogIC8vIEdlbmVyYXRlIG4gcmFuZG9tIHZhbHVlcyBhbmQgcHVzaCB0byBzdG9yYWdlCiAgTnVtYmVyc0luVmVjdG9yICAgICB2YWx1ZXMobmJyX29mX3JhbmRvbXMpOwogIHN0ZDo6Zm9yX2VhY2godmFsdWVzLmJlZ2luKCksIHZhbHVlcy5lbmQoKSwgWyZdKE51bWJlciYgbikgeyBuID0gcmFuZG9tX2ludCgwLCBuYnJfb2ZfcmFuZG9tcyAtMSk7fSk7IAoKICBUaW1lVmFsdWUgbGlzdF90aW1lOwogIFRpbWVWYWx1ZSB2ZWN0b3JfdGltZTsgIAogIFRpbWVWYWx1ZSBsaXN0X3RpbWVfcHJlYWxsb2NhdGVkOwoKICB7IC8vIExMCiAgICBOdW1iZXJzSW5MaXN0ICAgbGlzdDsKICAgIGxpc3RfdGltZSA9IGxpbmVhckluc2VydFBlcmZvcm1hbmNlKHZhbHVlcywgbGlzdCk7CiAgfQoKICB7IC8vIFZlY3RvcgogICAgTnVtYmVyc0luVmVjdG9yICAgIHZlY3RvcjsgCiAgICB2ZWN0b3JfdGltZSA9IGxpbmVhckluc2VydFBlcmZvcm1hbmNlKHZhbHVlcywgdmVjdG9yKTsgCiAgfQoKICB7IC8vIExMIC0gUHJlQWxsb2NhdGVkCiAgICBOdW1iZXJzSW5MaXN0ICAgbWVtb3J5X3Bvb2wobmJyX29mX3JhbmRvbXMsIC0xKTsgLy8gcHJlLWFsbG9jYXRlZCBMTCB1c2VkIGFzIG1lbW9yeSBwb29sCiAgICBOdW1iZXJzSW5MaXN0ICAgbGlzdF9wcmVhbGxvY2F0ZWQ7CiAgICBsaXN0X3RpbWVfcHJlYWxsb2NhdGVkID0gbGluZWFySW5zZXJ0UGVyZm9ybWFuY2UodmFsdWVzLCBtZW1vcnlfcG9vbCwgbGlzdF9wcmVhbGxvY2F0ZWQpOwogIH0KCiAgCgogIHN0ZDo6Y291dCA8PCBuYnJfb2ZfcmFuZG9tcyA8PCAiLCAgIiA8PCBzdGQ6OmZsdXNoOwogIHN0ZDo6Y291dCA8PCBsaXN0X3RpbWUgPDwgIiwgIiA8PCBsaXN0X3RpbWVfcHJlYWxsb2NhdGVkIDw8ICIsICIgPDwgdmVjdG9yX3RpbWUgPDwgc3RkOjplbmRsIDw8IHN0ZDo6Zmx1c2g7Cn0KCgoKCmludCBtYWluKGludCBhcmdjLCBjaGFyKiogYXJndikKeyAKICBzdGQ6OmNvdXQgPDwgIlByZS1hbGxvY2F0ZWQgbGlua2VkLWxpc3QgdnMgbGlua2VkLWxpc3QiIDw8IHN0ZDo6ZW5kbDsKICBzdGQ6OmNvdXQgPDwgIlRoaXMgc2hvd3MgaG93IG11Y2ggdGltZSBpcyBhY3R1YWxseSB1c2VkIGZvciBtZW1vcnkgYWxsb2NhdGlvbnMgaW4iIDw8IHN0ZDo6ZW5kbDsKICBzdGQ6OmNvdXQgPDwgInBlcnNwZWN0aXZlIHdpdGggY29zdCBmb3IgdHJhdmVyc2luZy4gQm90aCBsaXN0cyBhcmUgaW4gZGlzam9pbnQgbWVtb3J5ISIgPDwgc3RkOjplbmRsOwogIHN0ZDo6Y291dCA8PCAiXG4jaXRlbXMsIExMICh1cyksIExMIHByZS1hbGxvY2F0ZWQgKHVzKSAsIHZlY3RvciAodXMpICIgPDwgc3RkOjplbmRsOwoKCiAgZzI6OlN0b3BXYXRjaCB3YXRjaDsKICBsaW5rZWRfbGlzdFBlcmZvcm1hbmNlKDEwKTsKICBsaW5rZWRfbGlzdFBlcmZvcm1hbmNlKDEwMCk7CiAgbGlua2VkX2xpc3RQZXJmb3JtYW5jZSg1MDApOwogIGxpbmtlZF9saXN0UGVyZm9ybWFuY2UoMTAwMCk7CiAgbGlua2VkX2xpc3RQZXJmb3JtYW5jZSgyMDAwKTsKICBsaW5rZWRfbGlzdFBlcmZvcm1hbmNlKDEwMDAwKTsKICBsaW5rZWRfbGlzdFBlcmZvcm1hbmNlKDIwMDAwKTsKICBsaW5rZWRfbGlzdFBlcmZvcm1hbmNlKDQwMDAwKTsKICBsaW5rZWRfbGlzdFBlcmZvcm1hbmNlKDEwMDAwMCk7CiAgbGlua2VkX2xpc3RQZXJmb3JtYW5jZSg1MDAwMDApOwogIGxpbmtlZF9saXN0UGVyZm9ybWFuY2UoMTAwMDAwMCk7CgogIGF1dG8gdG90YWxfdGltZV9tcyA9IHdhdGNoLmVsYXBzZWRNcygpLmNvdW50KCk7CiAgc3RkOjpjb3V0IDw8ICJFeGl0aW5nIHRlc3QsLiB0aGUgd2hvbGUgbWVhc3VyaW5nIHRvb2sgIiA8PCB0b3RhbF90aW1lX21zIDw8ICIgbWlsbGlzZWNvbmRzIjsKICBzdGQ6OmNvdXQgPDwgIiAoIiA8PCB0b3RhbF90aW1lX21zLzEwMDAgPDwgInNlY29uZHMgb3IgIiA8PCB0b3RhbF90aW1lX21zLygxMDAwKjYwKSA8PCAiIG1pbnV0ZXMpIiA8PCBzdGQ6OmVuZGw7IAogICByZXR1cm4gMDsKfQ==
-
upload with new input
-
result: Time limit exceeded time: 15s memory: 4024 kB signal: 24 (SIGXCPU)
Pre-allocated linked-list vs linked-list This shows how much time is actually used for memory allocations in perspective with cost for traversing. Both lists are in disjoint memory! #items, LL (us), LL pre-allocated (us) , vector (us) 10, 2, 1, 3 100, 11, 7, 13 500, 118, 112, 116 1000, 412, 456, 396 2000, 1471, 1780, 1461 10000, 95107, 98522, 33494 20000, 588622, 603722, 138968 40000, 3434945, 3556232, 626431


