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.
|