[Assorted-commits] SF.net SVN: assorted: [435] sandbox/trunk/src/cc/custom_allocators.cc
Brought to you by:
yangzhang
From: <yan...@us...> - 2008-02-15 02:41:02
|
Revision: 435 http://assorted.svn.sourceforge.net/assorted/?rev=435&view=rev Author: yangzhang Date: 2008-02-14 18:41:07 -0800 (Thu, 14 Feb 2008) Log Message: ----------- added test for custom allocators, mainly for thread scalability Added Paths: ----------- sandbox/trunk/src/cc/custom_allocators.cc Added: sandbox/trunk/src/cc/custom_allocators.cc =================================================================== --- sandbox/trunk/src/cc/custom_allocators.cc (rev 0) +++ sandbox/trunk/src/cc/custom_allocators.cc 2008-02-15 02:41:07 UTC (rev 435) @@ -0,0 +1,87 @@ +// +// Microbenchmark for the hashtable, allocation, and the hashtable with a +// custom pool allocator. I was writing hash-join, and so I was interested in +// overcoming the scalability bottleneck that was the hashtable (namely, its +// allocator, which is just the default concurrency-unfriendly allocator). This +// eventually led me to create region_pool, since the available options were +// all less than ideal. +// + +#include <vector> +#include <ext/pool_allocator.h> +#include <ext/hash_map> +#include <boost/pool/pool.hpp> +#include <boost/pool/pool_alloc.hpp> + +#include <commons/time.h> +#include <commons/region.h> + +using namespace __gnu_cxx; +using namespace boost; +using namespace commons; +using namespace std; + +int +main() +{ + const int n = 1000000; + + { + // This just uses a default allocator, which calls new and delete. + hash_map<int,int> m; + timer t("hashtable: "); + for (int i = 0; i < n; i++) + m[i] = i; + t.print(); // 785 + } + + { + // This tries to just call new a delete a bunch of times. + timer t0("allocation: "); + int** xs = new int*[n]; + for (int i = 0; i < n; i++) { + xs[i] = new int[8]; + } + t0.print(); // 92 + timer t1("deallocation: "); + for (int i = 0; i < n; i++) { + delete [] xs[i]; + } + t1.print(); // 36 + } + + { + // __pool_alloc is from libstdc++, and was an old default, but was removed + // due to its complexity and lack of performance. + hash_map<int, int, hash<int>, equal_to<int>, __pool_alloc<int> > m; + timer t("hashtable with __pool_alloc: "); + for (int i = 0; i < n; i++) + m[i] = i; + t.print(); + } + + { + // pool_allocator is from boost, and uses boost::pool, but it's still a + // globally shared pool (so even if it doesn't use new/delete, it's still + // contending for the same nearby memory). + hash_map<int, int, hash<int>, equal_to<int>, pool_allocator<int> > m; + timer t("hashtable with pool: "); + for (int i = 0; i < n; i++) + m[i] = i; + t.print(); + } + + { + // region_alloc is home-rolled. It's hard to see any difference from this + // test - the number reported is roughly the same (or even worse). The + // default new/delete are undoubtedly highly optimized. However, the + // scalability effects are clear (see the analysis results of hash-join). + hash_map<int, int, hash<int>, equal_to<int>, region_alloc<int> > m; + timer t("hashtable with pool: "); + for (int i = 0; i < n; i++) + m[i] = i; + t.print(); // 818 + } + + return 0; +} This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |