google_hash 0.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README +21 -0
- data/Rakefile +11 -0
- data/VERSION +1 -0
- data/ext/extconf.rb +15 -0
- data/ext/go.cpp +109 -0
- data/ext/sparsehash-1.5.2/AUTHORS +2 -0
- data/ext/sparsehash-1.5.2/COPYING +28 -0
- data/ext/sparsehash-1.5.2/ChangeLog +167 -0
- data/ext/sparsehash-1.5.2/INSTALL +236 -0
- data/ext/sparsehash-1.5.2/Makefile.am +157 -0
- data/ext/sparsehash-1.5.2/Makefile.in +1019 -0
- data/ext/sparsehash-1.5.2/NEWS +0 -0
- data/ext/sparsehash-1.5.2/README +149 -0
- data/ext/sparsehash-1.5.2/README.windows +25 -0
- data/ext/sparsehash-1.5.2/TODO +28 -0
- data/ext/sparsehash-1.5.2/aclocal.m4 +868 -0
- data/ext/sparsehash-1.5.2/compile +99 -0
- data/ext/sparsehash-1.5.2/config.guess +1516 -0
- data/ext/sparsehash-1.5.2/config.sub +1626 -0
- data/ext/sparsehash-1.5.2/configure +8054 -0
- data/ext/sparsehash-1.5.2/configure.ac +74 -0
- data/ext/sparsehash-1.5.2/depcomp +530 -0
- data/ext/sparsehash-1.5.2/doc/dense_hash_map.html +1591 -0
- data/ext/sparsehash-1.5.2/doc/dense_hash_set.html +1445 -0
- data/ext/sparsehash-1.5.2/doc/designstyle.css +115 -0
- data/ext/sparsehash-1.5.2/doc/implementation.html +365 -0
- data/ext/sparsehash-1.5.2/doc/index.html +69 -0
- data/ext/sparsehash-1.5.2/doc/performance.html +96 -0
- data/ext/sparsehash-1.5.2/doc/sparse_hash_map.html +1527 -0
- data/ext/sparsehash-1.5.2/doc/sparse_hash_set.html +1376 -0
- data/ext/sparsehash-1.5.2/doc/sparsetable.html +1393 -0
- data/ext/sparsehash-1.5.2/experimental/Makefile +9 -0
- data/ext/sparsehash-1.5.2/experimental/README +14 -0
- data/ext/sparsehash-1.5.2/experimental/example.c +54 -0
- data/ext/sparsehash-1.5.2/experimental/libchash.c +1537 -0
- data/ext/sparsehash-1.5.2/experimental/libchash.h +252 -0
- data/ext/sparsehash-1.5.2/google-sparsehash.sln +47 -0
- data/ext/sparsehash-1.5.2/install-sh +323 -0
- data/ext/sparsehash-1.5.2/m4/acx_pthread.m4 +363 -0
- data/ext/sparsehash-1.5.2/m4/google_namespace.m4 +42 -0
- data/ext/sparsehash-1.5.2/m4/namespaces.m4 +15 -0
- data/ext/sparsehash-1.5.2/m4/stl_hash.m4 +70 -0
- data/ext/sparsehash-1.5.2/m4/stl_hash_fun.m4 +36 -0
- data/ext/sparsehash-1.5.2/m4/stl_namespace.m4 +25 -0
- data/ext/sparsehash-1.5.2/missing +360 -0
- data/ext/sparsehash-1.5.2/mkinstalldirs +158 -0
- data/ext/sparsehash-1.5.2/packages/deb.sh +74 -0
- data/ext/sparsehash-1.5.2/packages/deb/README +7 -0
- data/ext/sparsehash-1.5.2/packages/deb/changelog +107 -0
- data/ext/sparsehash-1.5.2/packages/deb/compat +1 -0
- data/ext/sparsehash-1.5.2/packages/deb/control +17 -0
- data/ext/sparsehash-1.5.2/packages/deb/copyright +35 -0
- data/ext/sparsehash-1.5.2/packages/deb/docs +16 -0
- data/ext/sparsehash-1.5.2/packages/deb/rules +117 -0
- data/ext/sparsehash-1.5.2/packages/deb/sparsehash.dirs +2 -0
- data/ext/sparsehash-1.5.2/packages/deb/sparsehash.install +2 -0
- data/ext/sparsehash-1.5.2/packages/rpm.sh +86 -0
- data/ext/sparsehash-1.5.2/packages/rpm/rpm.spec +61 -0
- data/ext/sparsehash-1.5.2/src/config.h.in +131 -0
- data/ext/sparsehash-1.5.2/src/config.h.include +23 -0
- data/ext/sparsehash-1.5.2/src/google/dense_hash_map +310 -0
- data/ext/sparsehash-1.5.2/src/google/dense_hash_set +287 -0
- data/ext/sparsehash-1.5.2/src/google/sparse_hash_map +294 -0
- data/ext/sparsehash-1.5.2/src/google/sparse_hash_set +275 -0
- data/ext/sparsehash-1.5.2/src/google/sparsehash/densehashtable.h +1062 -0
- data/ext/sparsehash-1.5.2/src/google/sparsehash/sparsehashtable.h +1015 -0
- data/ext/sparsehash-1.5.2/src/google/sparsetable +1468 -0
- data/ext/sparsehash-1.5.2/src/google/type_traits.h +250 -0
- data/ext/sparsehash-1.5.2/src/hashtable_unittest.cc +1375 -0
- data/ext/sparsehash-1.5.2/src/simple_test.cc +103 -0
- data/ext/sparsehash-1.5.2/src/sparsetable_unittest.cc +696 -0
- data/ext/sparsehash-1.5.2/src/time_hash_map.cc +488 -0
- data/ext/sparsehash-1.5.2/src/type_traits_unittest.cc +492 -0
- data/ext/sparsehash-1.5.2/src/windows/config.h +149 -0
- data/ext/sparsehash-1.5.2/src/windows/google/sparsehash/sparseconfig.h +32 -0
- data/ext/sparsehash-1.5.2/src/windows/port.cc +63 -0
- data/ext/sparsehash-1.5.2/src/windows/port.h +81 -0
- data/ext/sparsehash-1.5.2/src/words +8944 -0
- data/ext/sparsehash-1.5.2/vsprojects/hashtable_unittest/hashtable_unittest.vcproj +187 -0
- data/ext/sparsehash-1.5.2/vsprojects/sparsetable_unittest/sparsetable_unittest.vcproj +172 -0
- data/ext/sparsehash-1.5.2/vsprojects/time_hash_map/time_hash_map.vcproj +187 -0
- data/ext/sparsehash-1.5.2/vsprojects/type_traits_unittest/type_traits_unittest.vcproj +169 -0
- data/ext/test.rb +10 -0
- data/test/spec.go +70 -0
- metadata +147 -0
|
@@ -0,0 +1,488 @@
|
|
|
1
|
+
// Copyright (c) 2005, Google Inc.
|
|
2
|
+
// All rights reserved.
|
|
3
|
+
//
|
|
4
|
+
// Redistribution and use in source and binary forms, with or without
|
|
5
|
+
// modification, are permitted provided that the following conditions are
|
|
6
|
+
// met:
|
|
7
|
+
//
|
|
8
|
+
// * Redistributions of source code must retain the above copyright
|
|
9
|
+
// notice, this list of conditions and the following disclaimer.
|
|
10
|
+
// * Redistributions in binary form must reproduce the above
|
|
11
|
+
// copyright notice, this list of conditions and the following disclaimer
|
|
12
|
+
// in the documentation and/or other materials provided with the
|
|
13
|
+
// distribution.
|
|
14
|
+
// * Neither the name of Google Inc. nor the names of its
|
|
15
|
+
// contributors may be used to endorse or promote products derived from
|
|
16
|
+
// this software without specific prior written permission.
|
|
17
|
+
//
|
|
18
|
+
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
19
|
+
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
20
|
+
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
21
|
+
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
22
|
+
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
23
|
+
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
24
|
+
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
25
|
+
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
26
|
+
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
27
|
+
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
28
|
+
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
29
|
+
|
|
30
|
+
// ---
|
|
31
|
+
// Authors: Sanjay Ghemawat and Craig Silverstein
|
|
32
|
+
//
|
|
33
|
+
// Time various hash map implementations
|
|
34
|
+
//
|
|
35
|
+
// See PERFORMANCE for the output of one example run.
|
|
36
|
+
|
|
37
|
+
#include "config.h"
|
|
38
|
+
#include <stdio.h>
|
|
39
|
+
#include <stdlib.h>
|
|
40
|
+
#include <string.h>
|
|
41
|
+
extern "C" {
|
|
42
|
+
#include <time.h>
|
|
43
|
+
#ifdef HAVE_SYS_TIME_H
|
|
44
|
+
#include <sys/time.h>
|
|
45
|
+
#endif
|
|
46
|
+
#ifdef HAVE_SYS_RESOURCE_H
|
|
47
|
+
#include <sys/resource.h>
|
|
48
|
+
#endif
|
|
49
|
+
#ifdef HAVE_SYS_UTSNAME_H
|
|
50
|
+
#include <sys/utsname.h> // for uname()
|
|
51
|
+
#endif
|
|
52
|
+
#ifdef HAVE_WINDOWS_H
|
|
53
|
+
#include <Windows.h> // for GetTickCount()
|
|
54
|
+
#endif
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// The functions that we call on each map, that differ for different types.
|
|
58
|
+
// By default each is a noop, but we redefine them for types that need them.
|
|
59
|
+
|
|
60
|
+
#include <map>
|
|
61
|
+
#include HASH_MAP_H
|
|
62
|
+
#include <google/type_traits.h>
|
|
63
|
+
|
|
64
|
+
#include <google/sparse_hash_map>
|
|
65
|
+
using GOOGLE_NAMESPACE::sparse_hash_map;
|
|
66
|
+
|
|
67
|
+
#include <google/dense_hash_map>
|
|
68
|
+
using GOOGLE_NAMESPACE::dense_hash_map;
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
static const int kDefaultIters = 10000000;
|
|
72
|
+
|
|
73
|
+
// Normally I don't like non-const references, but using them here ensures
|
|
74
|
+
// the inlined code ends up as efficient as possible.
|
|
75
|
+
|
|
76
|
+
// These are operations that are supported on some hash impls but not others
|
|
77
|
+
template<class MapType> inline void SET_DELETED_KEY(MapType& m, int key) {}
|
|
78
|
+
template<class MapType> inline void SET_EMPTY_KEY(MapType& m, int key) {}
|
|
79
|
+
template<class MapType> inline void RESIZE(MapType& m, int iters) {}
|
|
80
|
+
|
|
81
|
+
template<class K, class V, class H>
|
|
82
|
+
inline void SET_DELETED_KEY(sparse_hash_map<K,V,H>& m, int key) {
|
|
83
|
+
m.set_deleted_key(key);
|
|
84
|
+
}
|
|
85
|
+
template<class K, class V, class H>
|
|
86
|
+
inline void SET_DELETED_KEY(dense_hash_map<K,V,H>& m, int key) {
|
|
87
|
+
m.set_deleted_key(key);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
template<class K, class V, class H>
|
|
91
|
+
inline void SET_EMPTY_KEY(dense_hash_map<K,V,H>& m, int key) {
|
|
92
|
+
m.set_empty_key(key);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
template<class K, class V, class H>
|
|
96
|
+
inline void RESIZE(sparse_hash_map<K,V,H>& m, int iters) {
|
|
97
|
+
m.resize(iters);
|
|
98
|
+
}
|
|
99
|
+
template<class K, class V, class H>
|
|
100
|
+
inline void RESIZE(dense_hash_map<K,V,H>& m, int iters) {
|
|
101
|
+
m.resize(iters);
|
|
102
|
+
}
|
|
103
|
+
#if defined(HAVE_UNORDERED_MAP)
|
|
104
|
+
template<class K, class V, class H>
|
|
105
|
+
inline void RESIZE(HASH_NAMESPACE::unordered_map<K,V,H>& m, int iters) {
|
|
106
|
+
m.rehash(iters); // the tr1 name for resize()
|
|
107
|
+
}
|
|
108
|
+
#elif defined(HAVE_HASH_MAP)
|
|
109
|
+
template<class K, class V, class H>
|
|
110
|
+
inline void RESIZE(HASH_NAMESPACE::hash_map<K,V,H>& m, int iters) {
|
|
111
|
+
#ifndef _MSC_VER /* apparently windows hash_map doesn't support resizing */
|
|
112
|
+
m.resize(iters);
|
|
113
|
+
#endif // _MSC_VER
|
|
114
|
+
}
|
|
115
|
+
#endif // HAVE_HASH_MAP
|
|
116
|
+
|
|
117
|
+
/*
|
|
118
|
+
* These are the objects we hash. Size is the size of the object
|
|
119
|
+
* (must be > sizeof(int). Hashsize is how many of these bytes we
|
|
120
|
+
* use when hashing (must be > sizeof(int) and < Size).
|
|
121
|
+
*/
|
|
122
|
+
template<int Size, int Hashsize> class HashObject {
|
|
123
|
+
public:
|
|
124
|
+
typedef HashObject<Size, Hashsize> class_type;
|
|
125
|
+
HashObject() {}
|
|
126
|
+
HashObject(int i) : i_(i) {
|
|
127
|
+
memset(buffer_, i & 255, sizeof(buffer_)); // a "random" char
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
size_t Hash() const {
|
|
131
|
+
int hashval = i_;
|
|
132
|
+
for (int i = 0; i < Hashsize - sizeof(i_); ++i) {
|
|
133
|
+
hashval += buffer_[i];
|
|
134
|
+
}
|
|
135
|
+
return SPARSEHASH_HASH<int>()(hashval); // defined in sparseconfig.h
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
bool operator==(const class_type& that) const { return this->i_ == that.i_; }
|
|
139
|
+
bool operator< (const class_type& that) const { return this->i_ < that.i_; }
|
|
140
|
+
bool operator<=(const class_type& that) const { return this->i_ <= that.i_; }
|
|
141
|
+
|
|
142
|
+
private:
|
|
143
|
+
int i_; // the key used for hashing
|
|
144
|
+
char buffer_[Size - sizeof(int)];
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
// A specialization for the case sizeof(buffer_) == 0
|
|
148
|
+
template<> class HashObject<sizeof(int), sizeof(int)> {
|
|
149
|
+
public:
|
|
150
|
+
typedef HashObject<sizeof(int), sizeof(int)> class_type;
|
|
151
|
+
HashObject() {}
|
|
152
|
+
HashObject(int i) : i_(i) {}
|
|
153
|
+
|
|
154
|
+
size_t Hash() const { return SPARSEHASH_HASH<int>()(i_); }
|
|
155
|
+
|
|
156
|
+
bool operator==(const class_type& that) const { return this->i_ == that.i_; }
|
|
157
|
+
bool operator< (const class_type& that) const { return this->i_ < that.i_; }
|
|
158
|
+
bool operator<=(const class_type& that) const { return this->i_ <= that.i_; }
|
|
159
|
+
|
|
160
|
+
private:
|
|
161
|
+
int i_; // the key used for hashing
|
|
162
|
+
};
|
|
163
|
+
|
|
164
|
+
// Let the hashtable implementations know it can use an optimized memcpy,
|
|
165
|
+
// because the compiler defines both the destructor and copy constructor.
|
|
166
|
+
|
|
167
|
+
_START_GOOGLE_NAMESPACE_
|
|
168
|
+
template<int Size, int Hashsize>
|
|
169
|
+
struct has_trivial_copy< HashObject<Size, Hashsize> > : true_type { };
|
|
170
|
+
|
|
171
|
+
template<int Size, int Hashsize>
|
|
172
|
+
struct has_trivial_destructor< HashObject<Size, Hashsize> > : true_type { };
|
|
173
|
+
_END_GOOGLE_NAMESPACE_
|
|
174
|
+
|
|
175
|
+
class HashFn {
|
|
176
|
+
public:
|
|
177
|
+
template<int Size, int Hashsize>
|
|
178
|
+
size_t operator()(const HashObject<Size,Hashsize>& obj) const {
|
|
179
|
+
return obj.Hash();
|
|
180
|
+
}
|
|
181
|
+
// For windows
|
|
182
|
+
template<int Size, int Hashsize>
|
|
183
|
+
bool operator()(const HashObject<Size,Hashsize>& a,
|
|
184
|
+
const HashObject<Size,Hashsize>& b) const {
|
|
185
|
+
return a < b;
|
|
186
|
+
}
|
|
187
|
+
// These two public members are required by msvc. 4 and 8 are defaults.
|
|
188
|
+
static const size_t bucket_size = 4;
|
|
189
|
+
static const size_t min_buckets = 8;
|
|
190
|
+
};
|
|
191
|
+
|
|
192
|
+
/*
|
|
193
|
+
* Measure resource usage.
|
|
194
|
+
*/
|
|
195
|
+
|
|
196
|
+
class Rusage {
|
|
197
|
+
public:
|
|
198
|
+
/* Start collecting usage */
|
|
199
|
+
Rusage() { Reset(); }
|
|
200
|
+
|
|
201
|
+
/* Reset collection */
|
|
202
|
+
void Reset();
|
|
203
|
+
|
|
204
|
+
/* Show usage */
|
|
205
|
+
double UserTime();
|
|
206
|
+
|
|
207
|
+
private:
|
|
208
|
+
#if defined HAVE_SYS_RESOURCE_H
|
|
209
|
+
struct rusage start;
|
|
210
|
+
#elif defined HAVE_WINDOWS_H
|
|
211
|
+
long long int start;
|
|
212
|
+
#else
|
|
213
|
+
time_t start_time_t;
|
|
214
|
+
#endif
|
|
215
|
+
};
|
|
216
|
+
|
|
217
|
+
inline void Rusage::Reset() {
|
|
218
|
+
#if defined HAVE_SYS_RESOURCE_H
|
|
219
|
+
getrusage(RUSAGE_SELF, &start);
|
|
220
|
+
#elif defined HAVE_WINDOWS_H
|
|
221
|
+
start = GetTickCount();
|
|
222
|
+
#else
|
|
223
|
+
time(&start_time_t);
|
|
224
|
+
#endif
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
inline double Rusage::UserTime() {
|
|
228
|
+
#if defined HAVE_SYS_RESOURCE_H
|
|
229
|
+
struct rusage u;
|
|
230
|
+
|
|
231
|
+
getrusage(RUSAGE_SELF, &u);
|
|
232
|
+
|
|
233
|
+
struct timeval result;
|
|
234
|
+
result.tv_sec = u.ru_utime.tv_sec - start.ru_utime.tv_sec;
|
|
235
|
+
result.tv_usec = u.ru_utime.tv_usec - start.ru_utime.tv_usec;
|
|
236
|
+
|
|
237
|
+
return double(result.tv_sec) + double(result.tv_usec) / 1000000.0;
|
|
238
|
+
#elif defined HAVE_WINDOWS_H
|
|
239
|
+
return double(GetTickCount() - start) / 1000.0;
|
|
240
|
+
#else
|
|
241
|
+
time_t now;
|
|
242
|
+
time(&now);
|
|
243
|
+
return now - start_time_t;
|
|
244
|
+
#endif
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
|
|
248
|
+
static void print_uname() {
|
|
249
|
+
#ifdef HAVE_SYS_UTSNAME_H
|
|
250
|
+
struct utsname u;
|
|
251
|
+
if (uname(&u) == 0) {
|
|
252
|
+
printf("%s %s %s %s %s\n",
|
|
253
|
+
u.sysname, u.nodename, u.release, u.version, u.machine);
|
|
254
|
+
}
|
|
255
|
+
#endif
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
// Generate stamp for this run
|
|
259
|
+
static void stamp_run(int iters) {
|
|
260
|
+
time_t now = time(0);
|
|
261
|
+
printf("======\n");
|
|
262
|
+
fflush(stdout);
|
|
263
|
+
print_uname();
|
|
264
|
+
printf("Average over %d iterations\n", iters);
|
|
265
|
+
fflush(stdout);
|
|
266
|
+
// don't need asctime_r/gmtime_r: we're not threaded
|
|
267
|
+
printf("Current time (GMT): %s", asctime(gmtime(&now)));
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
// If you have google-perftools (http://code.google.com/p/google-perftools),
|
|
271
|
+
// then you can figure out how much memory these implementations use
|
|
272
|
+
// as well.
|
|
273
|
+
#ifdef HAVE_GOOGLE_MALLOC_EXTENSION_H
|
|
274
|
+
#include <google/malloc_extension.h>
|
|
275
|
+
|
|
276
|
+
static size_t CurrentMemoryUsage() {
|
|
277
|
+
size_t result;
|
|
278
|
+
if (MallocExtension::instance()->GetNumericProperty(
|
|
279
|
+
"generic.current_allocated_bytes",
|
|
280
|
+
&result)) {
|
|
281
|
+
return result;
|
|
282
|
+
} else {
|
|
283
|
+
return 0;
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
#else /* not HAVE_GOOGLE_MALLOC_EXTENSION_H */
|
|
288
|
+
static size_t CurrentMemoryUsage() { return 0; }
|
|
289
|
+
|
|
290
|
+
#endif
|
|
291
|
+
|
|
292
|
+
static void report(char const* title, double t,
|
|
293
|
+
int iters,
|
|
294
|
+
size_t heap_growth) {
|
|
295
|
+
// Construct heap growth report text if applicable
|
|
296
|
+
char heap[100];
|
|
297
|
+
if (heap_growth > 0) {
|
|
298
|
+
snprintf(heap, sizeof(heap), "%8.1f MB", heap_growth / 1048576.0);
|
|
299
|
+
} else {
|
|
300
|
+
heap[0] = '\0';
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
printf("%-20s %8.1f ns %s\n", title, (t * 1000000000.0 / iters), heap);
|
|
304
|
+
fflush(stdout);
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
template<class MapType>
|
|
308
|
+
static void time_map_grow(int iters) {
|
|
309
|
+
MapType set;
|
|
310
|
+
Rusage t;
|
|
311
|
+
|
|
312
|
+
SET_EMPTY_KEY(set, -2);
|
|
313
|
+
const size_t start = CurrentMemoryUsage();
|
|
314
|
+
t.Reset();
|
|
315
|
+
for (int i = 0; i < iters; i++) {
|
|
316
|
+
set[i] = i+1;
|
|
317
|
+
}
|
|
318
|
+
double ut = t.UserTime();
|
|
319
|
+
const size_t finish = CurrentMemoryUsage();
|
|
320
|
+
report("map_grow", ut, iters, finish - start);
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
template<class MapType>
|
|
324
|
+
static void time_map_grow_predicted(int iters) {
|
|
325
|
+
MapType set;
|
|
326
|
+
Rusage t;
|
|
327
|
+
|
|
328
|
+
SET_EMPTY_KEY(set, -2);
|
|
329
|
+
const size_t start = CurrentMemoryUsage();
|
|
330
|
+
RESIZE(set, iters);
|
|
331
|
+
t.Reset();
|
|
332
|
+
for (int i = 0; i < iters; i++) {
|
|
333
|
+
set[i] = i+1;
|
|
334
|
+
}
|
|
335
|
+
double ut = t.UserTime();
|
|
336
|
+
const size_t finish = CurrentMemoryUsage();
|
|
337
|
+
report("map_predict/grow", ut, iters, finish - start);
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
template<class MapType>
|
|
341
|
+
static void time_map_replace(int iters) {
|
|
342
|
+
MapType set;
|
|
343
|
+
Rusage t;
|
|
344
|
+
int i;
|
|
345
|
+
|
|
346
|
+
SET_EMPTY_KEY(set, -2);
|
|
347
|
+
for (i = 0; i < iters; i++) {
|
|
348
|
+
set[i] = i+1;
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
t.Reset();
|
|
352
|
+
for (i = 0; i < iters; i++) {
|
|
353
|
+
set[i] = i+1;
|
|
354
|
+
}
|
|
355
|
+
double ut = t.UserTime();
|
|
356
|
+
|
|
357
|
+
report("map_replace", ut, iters, 0);
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
template<class MapType>
|
|
361
|
+
static void time_map_fetch(int iters) {
|
|
362
|
+
MapType set;
|
|
363
|
+
Rusage t;
|
|
364
|
+
int r;
|
|
365
|
+
int i;
|
|
366
|
+
|
|
367
|
+
SET_EMPTY_KEY(set, -2);
|
|
368
|
+
for (i = 0; i < iters; i++) {
|
|
369
|
+
set[i] = i+1;
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
r = 1;
|
|
373
|
+
t.Reset();
|
|
374
|
+
for (i = 0; i < iters; i++) {
|
|
375
|
+
r ^= static_cast<int>(set.find(i) != set.end());
|
|
376
|
+
}
|
|
377
|
+
double ut = t.UserTime();
|
|
378
|
+
|
|
379
|
+
srand(r); // keep compiler from optimizing away r (we never call rand())
|
|
380
|
+
report("map_fetch", ut, iters, 0);
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
template<class MapType>
|
|
384
|
+
static void time_map_fetch_empty(int iters) {
|
|
385
|
+
MapType set;
|
|
386
|
+
Rusage t;
|
|
387
|
+
int r;
|
|
388
|
+
int i;
|
|
389
|
+
|
|
390
|
+
SET_EMPTY_KEY(set, -2);
|
|
391
|
+
r = 1;
|
|
392
|
+
t.Reset();
|
|
393
|
+
for (i = 0; i < iters; i++) {
|
|
394
|
+
r ^= static_cast<int>(set.find(i) != set.end());
|
|
395
|
+
}
|
|
396
|
+
double ut = t.UserTime();
|
|
397
|
+
|
|
398
|
+
srand(r); // keep compiler from optimizing away r (we never call rand())
|
|
399
|
+
report("map_fetch_empty", ut, iters, 0);
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
template<class MapType>
|
|
403
|
+
static void time_map_remove(int iters) {
|
|
404
|
+
MapType set;
|
|
405
|
+
Rusage t;
|
|
406
|
+
int i;
|
|
407
|
+
|
|
408
|
+
SET_EMPTY_KEY(set, -2);
|
|
409
|
+
for (i = 0; i < iters; i++) {
|
|
410
|
+
set[i] = i+1;
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
t.Reset();
|
|
414
|
+
SET_DELETED_KEY(set, -1);
|
|
415
|
+
for (i = 0; i < iters; i++) {
|
|
416
|
+
set.erase(i);
|
|
417
|
+
}
|
|
418
|
+
double ut = t.UserTime();
|
|
419
|
+
|
|
420
|
+
report("map_remove", ut, iters, 0);
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
template<class MapType>
|
|
424
|
+
static void time_map_toggle(int iters) {
|
|
425
|
+
MapType set;
|
|
426
|
+
Rusage t;
|
|
427
|
+
int i;
|
|
428
|
+
|
|
429
|
+
const size_t start = CurrentMemoryUsage();
|
|
430
|
+
t.Reset();
|
|
431
|
+
SET_DELETED_KEY(set, -1);
|
|
432
|
+
SET_EMPTY_KEY(set, -2);
|
|
433
|
+
for (i = 0; i < iters; i++) {
|
|
434
|
+
set[i] = i+1;
|
|
435
|
+
set.erase(i);
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
double ut = t.UserTime();
|
|
439
|
+
const size_t finish = CurrentMemoryUsage();
|
|
440
|
+
|
|
441
|
+
report("map_toggle", ut, iters, finish - start);
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
template<class MapType>
|
|
445
|
+
static void measure_map(const char* label, int iters) {
|
|
446
|
+
printf("\n%s:\n", label);
|
|
447
|
+
if (1) time_map_grow<MapType>(iters);
|
|
448
|
+
if (1) time_map_grow_predicted<MapType>(iters);
|
|
449
|
+
if (1) time_map_replace<MapType>(iters);
|
|
450
|
+
if (1) time_map_fetch<MapType>(iters);
|
|
451
|
+
if (1) time_map_fetch_empty<MapType>(iters);
|
|
452
|
+
if (1) time_map_remove<MapType>(iters);
|
|
453
|
+
if (1) time_map_toggle<MapType>(iters);
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
int main(int argc, char** argv) {
|
|
457
|
+
int iters = kDefaultIters;
|
|
458
|
+
if (argc > 1) { // first arg is # of iterations
|
|
459
|
+
iters = atoi(argv[1]);
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
// It would be nice to set these at run-time, but by setting them at
|
|
463
|
+
// compile-time, we allow optimizations that make it as fast to use
|
|
464
|
+
// a HashObject as it would be to use just a straight int/char buffer.
|
|
465
|
+
const int obj_size = 4;
|
|
466
|
+
const int hash_size = 4;
|
|
467
|
+
typedef HashObject<obj_size, hash_size> HashObj;
|
|
468
|
+
|
|
469
|
+
stamp_run(iters);
|
|
470
|
+
|
|
471
|
+
#ifndef HAVE_SYS_RESOURCE_H
|
|
472
|
+
printf("\n*** WARNING ***: sys/resources.h was not found, so all times\n"
|
|
473
|
+
" reported are wall-clock time, not user time\n");
|
|
474
|
+
#endif
|
|
475
|
+
|
|
476
|
+
measure_map< sparse_hash_map<HashObj,int,HashFn> >("SPARSE_HASH_MAP", iters);
|
|
477
|
+
measure_map< dense_hash_map<HashObj,int,HashFn> >("DENSE_HASH_MAP", iters);
|
|
478
|
+
#if defined(HAVE_UNORDERED_MAP)
|
|
479
|
+
measure_map< HASH_NAMESPACE::unordered_map<HashObj,int,HashFn> >(
|
|
480
|
+
"TR1 UNORDERED_MAP", iters);
|
|
481
|
+
#elif defined(HAVE_HASH_MAP)
|
|
482
|
+
measure_map< HASH_NAMESPACE::hash_map<HashObj,int,HashFn> >(
|
|
483
|
+
"STANDARD HASH_MAP", iters);
|
|
484
|
+
#endif
|
|
485
|
+
measure_map< STL_NAMESPACE::map<HashObj,int,HashFn> >("STANDARD MAP", iters);
|
|
486
|
+
|
|
487
|
+
return 0;
|
|
488
|
+
}
|