google_hash 0.8.1 → 0.8.2
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/ChangeLog.txt +2 -0
- data/VERSION +1 -1
- data/ext/clean.bat +0 -0
- data/ext/clean.sh +4 -0
- data/ext/extconf.rb +4 -5
- data/ext/go.bat +0 -0
- data/ext/sparsehash-2.0.2/AUTHORS +2 -0
- data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/COPYING +0 -0
- data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/ChangeLog +60 -0
- data/ext/sparsehash-2.0.2/INSTALL +365 -0
- data/ext/sparsehash-2.0.2/Makefile +1336 -0
- data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/Makefile.am +97 -40
- data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/Makefile.in +538 -256
- data/ext/sparsehash-2.0.2/NEWS +188 -0
- data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/README +4 -10
- data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/README_windows.txt +3 -3
- data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/TODO +0 -0
- data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/aclocal.m4 +266 -166
- data/ext/sparsehash-2.0.2/allocator.patch +31 -0
- data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/config.guess +235 -234
- data/ext/sparsehash-2.0.2/config.status +1238 -0
- data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/config.sub +198 -64
- data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/configure +1118 -1000
- data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/configure.ac +4 -5
- data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/depcomp +136 -36
- data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/doc/dense_hash_map.html +182 -67
- data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/doc/dense_hash_set.html +173 -74
- data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/doc/designstyle.css +0 -6
- data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/doc/implementation.html +0 -0
- data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/doc/index.html +4 -5
- data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/doc/performance.html +1 -1
- data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/doc/sparse_hash_map.html +190 -58
- data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/doc/sparse_hash_set.html +180 -65
- data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/doc/sparsetable.html +1 -1
- data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/experimental/Makefile +0 -0
- data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/experimental/README +0 -0
- data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/experimental/example.c +1 -0
- data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/experimental/libchash.c +1 -0
- data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/experimental/libchash.h +1 -0
- data/ext/sparsehash-2.0.2/install-sh +520 -0
- data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/m4/acx_pthread.m4 +34 -0
- data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/m4/google_namespace.m4 +0 -0
- data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/m4/namespaces.m4 +0 -0
- data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/m4/stl_hash.m4 +0 -0
- data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/m4/stl_hash_fun.m4 +0 -0
- data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/missing +60 -44
- data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/packages/deb.sh +0 -0
- data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/packages/deb/README +0 -0
- data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/packages/deb/changelog +42 -0
- data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/packages/deb/compat +0 -0
- data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/packages/deb/control +1 -1
- data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/packages/deb/copyright +5 -4
- data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/packages/deb/docs +0 -0
- data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/packages/deb/rules +0 -0
- data/ext/sparsehash-2.0.2/packages/deb/sparsehash.dirs +5 -0
- data/ext/sparsehash-2.0.2/packages/deb/sparsehash.install +6 -0
- data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/packages/rpm.sh +1 -1
- data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/packages/rpm/rpm.spec +5 -3
- data/ext/{sparsehash-1.8.1/google-sparsehash.sln → sparsehash-2.0.2/sparsehash.sln} +0 -0
- data/ext/sparsehash-2.0.2/src/config.h +132 -0
- data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/src/config.h.in +0 -3
- data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/src/config.h.include +0 -1
- data/ext/sparsehash-2.0.2/src/google/dense_hash_map +34 -0
- data/ext/sparsehash-2.0.2/src/google/dense_hash_set +34 -0
- data/ext/sparsehash-2.0.2/src/google/sparse_hash_map +34 -0
- data/ext/sparsehash-2.0.2/src/google/sparse_hash_set +34 -0
- data/ext/sparsehash-2.0.2/src/google/sparsehash/densehashtable.h +34 -0
- data/ext/sparsehash-2.0.2/src/google/sparsehash/hashtable-common.h +34 -0
- data/ext/sparsehash-2.0.2/src/google/sparsehash/libc_allocator_with_realloc.h +34 -0
- data/ext/sparsehash-2.0.2/src/google/sparsehash/sparsehashtable.h +34 -0
- data/ext/sparsehash-2.0.2/src/google/sparsetable +34 -0
- data/ext/sparsehash-2.0.2/src/google/template_util.h +34 -0
- data/ext/sparsehash-2.0.2/src/google/type_traits.h +34 -0
- data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/src/hash_test_interface.h +64 -37
- data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/src/hashtable_test.cc +415 -141
- data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/src/libc_allocator_with_realloc_test.cc +16 -23
- data/ext/sparsehash-2.0.2/src/simple_compat_test.cc +106 -0
- data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/src/simple_test.cc +8 -5
- data/ext/{sparsehash-1.8.1/src/google → sparsehash-2.0.2/src/sparsehash}/dense_hash_map +80 -37
- data/ext/{sparsehash-1.8.1/src/google → sparsehash-2.0.2/src/sparsehash}/dense_hash_set +64 -34
- data/ext/{sparsehash-1.8.1/src/google/sparsehash → sparsehash-2.0.2/src/sparsehash/internal}/densehashtable.h +247 -173
- data/ext/sparsehash-2.0.2/src/sparsehash/internal/hashtable-common.h +381 -0
- data/ext/{sparsehash-1.8.1/src/google/sparsehash → sparsehash-2.0.2/src/sparsehash/internal}/libc_allocator_with_realloc.h +5 -7
- data/ext/{sparsehash-1.8.1/src/google/sparsehash → sparsehash-2.0.2/src/sparsehash/internal}/sparsehashtable.h +154 -93
- data/ext/{sparsehash-1.8.1/src/google → sparsehash-2.0.2/src/sparsehash}/sparse_hash_map +96 -36
- data/ext/{sparsehash-1.8.1/src/google → sparsehash-2.0.2/src/sparsehash}/sparse_hash_set +85 -32
- data/ext/{sparsehash-1.8.1/src/google → sparsehash-2.0.2/src/sparsehash}/sparsetable +520 -258
- data/ext/sparsehash-2.0.2/src/sparsehash/template_util.h +134 -0
- data/ext/{sparsehash-1.8.1/src/google → sparsehash-2.0.2/src/sparsehash}/type_traits.h +153 -35
- data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/src/sparsetable_unittest.cc +108 -22
- data/ext/sparsehash-2.0.2/src/stamp-h1 +1 -0
- data/ext/sparsehash-2.0.2/src/template_util_unittest.cc +134 -0
- data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/src/testutil.h +16 -1
- data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/src/time_hash_map.cc +259 -94
- data/ext/sparsehash-2.0.2/src/type_traits_unittest.cc +636 -0
- data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/src/windows/config.h +4 -4
- data/ext/sparsehash-2.0.2/src/windows/google/sparsehash/sparseconfig.h +49 -0
- data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/src/windows/port.cc +1 -0
- data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/src/windows/port.h +4 -13
- data/ext/sparsehash-2.0.2/src/windows/sparsehash/internal/sparseconfig.h +49 -0
- data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/vsprojects/hashtable_test/hashtable_test.vcproj +11 -11
- data/ext/sparsehash-2.0.2/vsprojects/libc_allocator_with_realloc_test/libc_allocator_with_realloc_test.vcproj +161 -0
- data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/vsprojects/simple_test/simple_test.vcproj +10 -10
- data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/vsprojects/sparsetable_unittest/sparsetable_unittest.vcproj +4 -4
- data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/vsprojects/time_hash_map/time_hash_map.vcproj +10 -10
- data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/vsprojects/type_traits_unittest/type_traits_unittest.vcproj +3 -3
- data/ext/spec.bat +0 -0
- data/ext/template/google_hash.cpp.erb +6 -5
- metadata +106 -86
- data/ext/sparsehash-1.8.1/AUTHORS +0 -2
- data/ext/sparsehash-1.8.1/INSTALL +0 -236
- data/ext/sparsehash-1.8.1/NEWS +0 -71
- data/ext/sparsehash-1.8.1/compile +0 -99
- data/ext/sparsehash-1.8.1/install-sh +0 -323
- data/ext/sparsehash-1.8.1/m4/stl_namespace.m4 +0 -25
- data/ext/sparsehash-1.8.1/mkinstalldirs +0 -158
- data/ext/sparsehash-1.8.1/packages/deb/sparsehash.dirs +0 -2
- data/ext/sparsehash-1.8.1/packages/deb/sparsehash.install +0 -2
- data/ext/sparsehash-1.8.1/src/google/sparsehash/hashtable-common.h +0 -178
- data/ext/sparsehash-1.8.1/src/type_traits_unittest.cc +0 -502
- data/ext/sparsehash-1.8.1/src/windows/google/sparsehash/sparseconfig.h +0 -32
|
@@ -0,0 +1 @@
|
|
|
1
|
+
timestamp for src/config.h
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
// Copyright 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
|
+
//
|
|
32
|
+
// These tests are really compile time tests.
|
|
33
|
+
// If you try to step through this in a debugger
|
|
34
|
+
// you will not see any evaluations, merely that
|
|
35
|
+
// value is assigned true or false sequentially.
|
|
36
|
+
|
|
37
|
+
#include <sparsehash/internal/sparseconfig.h>
|
|
38
|
+
#include <config.h>
|
|
39
|
+
#include <sparsehash/template_util.h>
|
|
40
|
+
|
|
41
|
+
#include "testutil.h"
|
|
42
|
+
|
|
43
|
+
using namespace GOOGLE_NAMESPACE;
|
|
44
|
+
|
|
45
|
+
namespace {
|
|
46
|
+
|
|
47
|
+
TEST(TemplateUtilTest, TestSize) {
|
|
48
|
+
EXPECT_GT(sizeof(GOOGLE_NAMESPACE::big_), sizeof(GOOGLE_NAMESPACE::small_));
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
TEST(TemplateUtilTest, TestIntegralConstants) {
|
|
52
|
+
// test the built-in types.
|
|
53
|
+
EXPECT_TRUE(true_type::value);
|
|
54
|
+
EXPECT_FALSE(false_type::value);
|
|
55
|
+
|
|
56
|
+
typedef integral_constant<int, 1> one_type;
|
|
57
|
+
EXPECT_EQ(1, one_type::value);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
TEST(TemplateUtilTest, TestTemplateIf) {
|
|
61
|
+
typedef if_<true, true_type, false_type>::type if_true;
|
|
62
|
+
EXPECT_TRUE(if_true::value);
|
|
63
|
+
|
|
64
|
+
typedef if_<false, true_type, false_type>::type if_false;
|
|
65
|
+
EXPECT_FALSE(if_false::value);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
TEST(TemplateUtilTest, TestTemplateTypeEquals) {
|
|
69
|
+
// Check that the TemplateTypeEquals works correctly.
|
|
70
|
+
bool value = false;
|
|
71
|
+
|
|
72
|
+
// Test the same type is true.
|
|
73
|
+
value = type_equals_<int, int>::value;
|
|
74
|
+
EXPECT_TRUE(value);
|
|
75
|
+
|
|
76
|
+
// Test different types are false.
|
|
77
|
+
value = type_equals_<float, int>::value;
|
|
78
|
+
EXPECT_FALSE(value);
|
|
79
|
+
|
|
80
|
+
// Test type aliasing.
|
|
81
|
+
typedef const int foo;
|
|
82
|
+
value = type_equals_<const foo, const int>::value;
|
|
83
|
+
EXPECT_TRUE(value);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
TEST(TemplateUtilTest, TestTemplateAndOr) {
|
|
87
|
+
// Check that the TemplateTypeEquals works correctly.
|
|
88
|
+
bool value = false;
|
|
89
|
+
|
|
90
|
+
// Yes && Yes == true.
|
|
91
|
+
value = and_<true_, true_>::value;
|
|
92
|
+
EXPECT_TRUE(value);
|
|
93
|
+
// Yes && No == false.
|
|
94
|
+
value = and_<true_, false_>::value;
|
|
95
|
+
EXPECT_FALSE(value);
|
|
96
|
+
// No && Yes == false.
|
|
97
|
+
value = and_<false_, true_>::value;
|
|
98
|
+
EXPECT_FALSE(value);
|
|
99
|
+
// No && No == false.
|
|
100
|
+
value = and_<false_, false_>::value;
|
|
101
|
+
EXPECT_FALSE(value);
|
|
102
|
+
|
|
103
|
+
// Yes || Yes == true.
|
|
104
|
+
value = or_<true_, true_>::value;
|
|
105
|
+
EXPECT_TRUE(value);
|
|
106
|
+
// Yes || No == true.
|
|
107
|
+
value = or_<true_, false_>::value;
|
|
108
|
+
EXPECT_TRUE(value);
|
|
109
|
+
// No || Yes == true.
|
|
110
|
+
value = or_<false_, true_>::value;
|
|
111
|
+
EXPECT_TRUE(value);
|
|
112
|
+
// No || No == false.
|
|
113
|
+
value = or_<false_, false_>::value;
|
|
114
|
+
EXPECT_FALSE(value);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
TEST(TemplateUtilTest, TestIdentity) {
|
|
118
|
+
EXPECT_TRUE(
|
|
119
|
+
(type_equals_<GOOGLE_NAMESPACE::identity_<int>::type, int>::value));
|
|
120
|
+
EXPECT_TRUE(
|
|
121
|
+
(type_equals_<GOOGLE_NAMESPACE::identity_<void>::type, void>::value));
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
} // namespace
|
|
125
|
+
|
|
126
|
+
#include <iostream>
|
|
127
|
+
|
|
128
|
+
int main(int, char **) {
|
|
129
|
+
// All the work is done in the static constructors. If they don't
|
|
130
|
+
// die, the tests have all passed.
|
|
131
|
+
std::cout << "PASS\n";
|
|
132
|
+
return 0;
|
|
133
|
+
}
|
|
134
|
+
|
|
@@ -28,7 +28,6 @@
|
|
|
28
28
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
29
29
|
|
|
30
30
|
// ---
|
|
31
|
-
// Author: Craig Silverstein
|
|
32
31
|
|
|
33
32
|
// This macro mimics a unittest framework, but is a bit less flexible
|
|
34
33
|
// than most. It requires a superclass to derive from, and does all
|
|
@@ -38,8 +37,11 @@
|
|
|
38
37
|
#ifndef SPARSEHASH_TEST_UTIL_H_
|
|
39
38
|
#define SPARSEHASH_TEST_UTIL_H_
|
|
40
39
|
|
|
40
|
+
#include <sparsehash/internal/sparseconfig.h>
|
|
41
41
|
#include "config.h"
|
|
42
42
|
#include <stdio.h>
|
|
43
|
+
#include <stdlib.h> // for exit
|
|
44
|
+
#include <stdexcept> // for length_error
|
|
43
45
|
|
|
44
46
|
_START_GOOGLE_NAMESPACE_
|
|
45
47
|
|
|
@@ -54,11 +56,20 @@ namespace testing {
|
|
|
54
56
|
|
|
55
57
|
#define EXPECT_FALSE(a) EXPECT_TRUE(!(a))
|
|
56
58
|
#define EXPECT_EQ(a, b) EXPECT_TRUE((a) == (b))
|
|
59
|
+
#define EXPECT_NE(a, b) EXPECT_TRUE((a) != (b))
|
|
57
60
|
#define EXPECT_LT(a, b) EXPECT_TRUE((a) < (b))
|
|
58
61
|
#define EXPECT_GT(a, b) EXPECT_TRUE((a) > (b))
|
|
59
62
|
#define EXPECT_LE(a, b) EXPECT_TRUE((a) <= (b))
|
|
60
63
|
#define EXPECT_GE(a, b) EXPECT_TRUE((a) >= (b))
|
|
61
64
|
|
|
65
|
+
#define EXPECT_DEATH(cmd, expected_error_string) \
|
|
66
|
+
try { \
|
|
67
|
+
cmd; \
|
|
68
|
+
EXPECT_FALSE("did not see expected error: " #expected_error_string); \
|
|
69
|
+
} catch (const std::length_error&) { \
|
|
70
|
+
/* Good, the cmd failed. */ \
|
|
71
|
+
}
|
|
72
|
+
|
|
62
73
|
#define TEST(suitename, testname) \
|
|
63
74
|
class TEST_##suitename##_##testname { \
|
|
64
75
|
public: \
|
|
@@ -244,6 +255,10 @@ template<typename C1, typename C2, typename C3, typename C4, typename C5,
|
|
|
244
255
|
template<class TypeParam> \
|
|
245
256
|
void TEST_onetype_##superclass##_##testname<TypeParam>::Run()
|
|
246
257
|
|
|
258
|
+
// This is a dummy class just to make converting from internal-google
|
|
259
|
+
// to opensourcing easier.
|
|
260
|
+
class Test { };
|
|
261
|
+
|
|
247
262
|
} // namespace testing
|
|
248
263
|
|
|
249
264
|
_END_GOOGLE_NAMESPACE_
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Copyright (c) 2005, Google Inc.
|
|
2
2
|
// All rights reserved.
|
|
3
|
-
//
|
|
3
|
+
//
|
|
4
4
|
// Redistribution and use in source and binary forms, with or without
|
|
5
5
|
// modification, are permitted provided that the following conditions are
|
|
6
6
|
// met:
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
// * Neither the name of Google Inc. nor the names of its
|
|
15
15
|
// contributors may be used to endorse or promote products derived from
|
|
16
16
|
// this software without specific prior written permission.
|
|
17
|
-
//
|
|
17
|
+
//
|
|
18
18
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
19
19
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
20
20
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
@@ -29,9 +29,21 @@
|
|
|
29
29
|
|
|
30
30
|
// ---
|
|
31
31
|
// Authors: Sanjay Ghemawat and Craig Silverstein
|
|
32
|
-
|
|
32
|
+
|
|
33
33
|
// Time various hash map implementations
|
|
34
34
|
//
|
|
35
|
+
// Below, times are per-call. "Memory use" is "bytes in use by
|
|
36
|
+
// application" as reported by tcmalloc, compared before and after the
|
|
37
|
+
// function call. This does not really report fragmentation, which is
|
|
38
|
+
// not bad for the sparse* routines but bad for the dense* ones.
|
|
39
|
+
//
|
|
40
|
+
// The tests generally yield best-case performance because the
|
|
41
|
+
// code uses sequential keys; on the other hand, "map_fetch_random" does
|
|
42
|
+
// lookups in a pseudorandom order. Also, "stresshashfunction" is
|
|
43
|
+
// a stress test of sorts. It uses keys from an arithmetic sequence, which,
|
|
44
|
+
// if combined with a quick-and-dirty hash function, will yield worse
|
|
45
|
+
// performance than the otherwise similar "map_predict/grow."
|
|
46
|
+
//
|
|
35
47
|
// Consider doing the following to get good numbers:
|
|
36
48
|
//
|
|
37
49
|
// 1. Run the tests on a machine with no X service. Make sure no other
|
|
@@ -42,24 +54,25 @@
|
|
|
42
54
|
//
|
|
43
55
|
// See PERFORMANCE for the output of one example run.
|
|
44
56
|
|
|
45
|
-
#include
|
|
57
|
+
#include <sparsehash/internal/sparseconfig.h>
|
|
58
|
+
#include <config.h>
|
|
59
|
+
#ifdef HAVE_INTTYPES_H
|
|
60
|
+
# include <inttypes.h>
|
|
61
|
+
#endif // for uintptr_t
|
|
46
62
|
#include <stdio.h>
|
|
47
63
|
#include <stdlib.h>
|
|
48
64
|
#include <string.h>
|
|
49
65
|
extern "C" {
|
|
50
66
|
#include <time.h>
|
|
51
67
|
#ifdef HAVE_SYS_TIME_H
|
|
52
|
-
#include <sys/time.h>
|
|
68
|
+
# include <sys/time.h>
|
|
53
69
|
#endif
|
|
54
70
|
#ifdef HAVE_SYS_RESOURCE_H
|
|
55
|
-
#include <sys/resource.h>
|
|
71
|
+
# include <sys/resource.h>
|
|
56
72
|
#endif
|
|
57
73
|
#ifdef HAVE_SYS_UTSNAME_H
|
|
58
|
-
#include <sys/utsname.h>
|
|
59
|
-
#endif
|
|
60
|
-
#ifdef HAVE_WINDOWS_H
|
|
61
|
-
#include <Windows.h> // for GetTickCount()
|
|
62
|
-
#endif
|
|
74
|
+
# include <sys/utsname.h>
|
|
75
|
+
#endif // for uname()
|
|
63
76
|
}
|
|
64
77
|
|
|
65
78
|
// The functions that we call on each map, that differ for different types.
|
|
@@ -67,14 +80,17 @@ extern "C" {
|
|
|
67
80
|
|
|
68
81
|
#include <map>
|
|
69
82
|
#include HASH_MAP_H
|
|
70
|
-
#include <
|
|
71
|
-
|
|
72
|
-
#include <
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
83
|
+
#include <algorithm>
|
|
84
|
+
#include <vector>
|
|
85
|
+
#include <sparsehash/type_traits.h>
|
|
86
|
+
#include <sparsehash/dense_hash_map>
|
|
87
|
+
#include <sparsehash/sparse_hash_map>
|
|
88
|
+
|
|
89
|
+
using std::map;
|
|
90
|
+
using std::swap;
|
|
91
|
+
using std::vector;
|
|
76
92
|
using GOOGLE_NAMESPACE::dense_hash_map;
|
|
77
|
-
|
|
93
|
+
using GOOGLE_NAMESPACE::sparse_hash_map;
|
|
78
94
|
|
|
79
95
|
static bool FLAGS_test_sparse_hash_map = true;
|
|
80
96
|
static bool FLAGS_test_dense_hash_map = true;
|
|
@@ -82,57 +98,85 @@ static bool FLAGS_test_hash_map = true;
|
|
|
82
98
|
static bool FLAGS_test_map = true;
|
|
83
99
|
|
|
84
100
|
static bool FLAGS_test_4_bytes = true;
|
|
101
|
+
static bool FLAGS_test_8_bytes = true;
|
|
85
102
|
static bool FLAGS_test_16_bytes = true;
|
|
86
103
|
static bool FLAGS_test_256_bytes = true;
|
|
87
104
|
|
|
105
|
+
#if defined(HAVE_UNORDERED_MAP)
|
|
106
|
+
using HASH_NAMESPACE::unordered_map;
|
|
107
|
+
#elif defined(HAVE_HASH_MAP) || defined(_MSC_VER)
|
|
108
|
+
using HASH_NAMESPACE::hash_map;
|
|
109
|
+
#endif
|
|
110
|
+
|
|
88
111
|
static const int kDefaultIters = 10000000;
|
|
89
112
|
|
|
90
|
-
//
|
|
91
|
-
//
|
|
113
|
+
// A version of each of the hashtable classes we test, that has been
|
|
114
|
+
// augumented to provide a common interface. For instance, the
|
|
115
|
+
// sparse_hash_map and dense_hash_map versions set empty-key and
|
|
116
|
+
// deleted-key (we can do this because all our tests use int-like
|
|
117
|
+
// keys), so the users don't have to. The hash_map version adds
|
|
118
|
+
// resize(), so users can just call resize() for all tests without
|
|
119
|
+
// worrying about whether the map-type supports it or not.
|
|
92
120
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
121
|
+
template<typename K, typename V, typename H>
|
|
122
|
+
class EasyUseSparseHashMap : public sparse_hash_map<K,V,H> {
|
|
123
|
+
public:
|
|
124
|
+
EasyUseSparseHashMap() {
|
|
125
|
+
this->set_deleted_key(-1);
|
|
126
|
+
}
|
|
127
|
+
};
|
|
97
128
|
|
|
98
|
-
template<
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
}
|
|
129
|
+
template<typename K, typename V, typename H>
|
|
130
|
+
class EasyUseDenseHashMap : public dense_hash_map<K,V,H> {
|
|
131
|
+
public:
|
|
132
|
+
EasyUseDenseHashMap() {
|
|
133
|
+
this->set_empty_key(-1);
|
|
134
|
+
this->set_deleted_key(-2);
|
|
135
|
+
}
|
|
136
|
+
};
|
|
106
137
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
138
|
+
// For pointers, we only set the empty key.
|
|
139
|
+
template<typename K, typename V, typename H>
|
|
140
|
+
class EasyUseSparseHashMap<K*, V, H> : public sparse_hash_map<K*,V,H> {
|
|
141
|
+
public:
|
|
142
|
+
EasyUseSparseHashMap() { }
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
template<typename K, typename V, typename H>
|
|
146
|
+
class EasyUseDenseHashMap<K*, V, H> : public dense_hash_map<K*,V,H> {
|
|
147
|
+
public:
|
|
148
|
+
EasyUseDenseHashMap() {
|
|
149
|
+
this->set_empty_key((K*)(~0));
|
|
150
|
+
}
|
|
151
|
+
};
|
|
111
152
|
|
|
112
|
-
template<class K, class V, class H, class E, class A>
|
|
113
|
-
inline void RESIZE(sparse_hash_map<K,V,H,E,A>& m, int iters) {
|
|
114
|
-
m.resize(iters);
|
|
115
|
-
}
|
|
116
|
-
template<class K, class V, class H, class E, class A>
|
|
117
|
-
inline void RESIZE(dense_hash_map<K,V,H,E,A>& m, int iters) {
|
|
118
|
-
m.resize(iters);
|
|
119
|
-
}
|
|
120
153
|
#if defined(HAVE_UNORDERED_MAP)
|
|
121
|
-
template<
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
154
|
+
template<typename K, typename V, typename H>
|
|
155
|
+
class EasyUseHashMap : public unordered_map<K,V,H> {
|
|
156
|
+
public:
|
|
157
|
+
// resize() is called rehash() in tr1
|
|
158
|
+
void resize(size_t r) { this->rehash(r); }
|
|
159
|
+
};
|
|
125
160
|
#elif defined(_MSC_VER)
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
}
|
|
161
|
+
template<typename K, typename V, typename H>
|
|
162
|
+
class EasyUseHashMap : public hash_map<K,V,H> {
|
|
163
|
+
public:
|
|
164
|
+
void resize(size_t r) { }
|
|
165
|
+
};
|
|
130
166
|
#elif defined(HAVE_HASH_MAP)
|
|
131
|
-
template<
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
167
|
+
template<typename K, typename V, typename H>
|
|
168
|
+
class EasyUseHashMap : public hash_map<K,V,H> {
|
|
169
|
+
public:
|
|
170
|
+
// Don't need to do anything: hash_map is already easy to use!
|
|
171
|
+
};
|
|
172
|
+
#endif
|
|
173
|
+
|
|
174
|
+
template<typename K, typename V>
|
|
175
|
+
class EasyUseMap : public map<K,V> {
|
|
176
|
+
public:
|
|
177
|
+
void resize(size_t) { } // map<> doesn't support resize
|
|
178
|
+
};
|
|
179
|
+
|
|
136
180
|
|
|
137
181
|
// Returns the number of hashes that have been done since the last
|
|
138
182
|
// call to NumHashesSinceLastCall(). This is shared across all
|
|
@@ -181,7 +225,7 @@ template<int Size, int Hashsize> class HashObject {
|
|
|
181
225
|
for (size_t i = 0; i < Hashsize - sizeof(i_); ++i) {
|
|
182
226
|
hashval += buffer_[i];
|
|
183
227
|
}
|
|
184
|
-
return SPARSEHASH_HASH<int>()(hashval);
|
|
228
|
+
return SPARSEHASH_HASH<int>()(hashval);
|
|
185
229
|
}
|
|
186
230
|
|
|
187
231
|
bool operator==(const class_type& that) const { return this->i_ == that.i_; }
|
|
@@ -220,15 +264,17 @@ template<> class HashObject<sizeof(int), sizeof(int)> {
|
|
|
220
264
|
int i_; // the key used for hashing
|
|
221
265
|
};
|
|
222
266
|
|
|
267
|
+
_START_GOOGLE_NAMESPACE_
|
|
268
|
+
|
|
223
269
|
// Let the hashtable implementations know it can use an optimized memcpy,
|
|
224
270
|
// because the compiler defines both the destructor and copy constructor.
|
|
225
271
|
|
|
226
|
-
_START_GOOGLE_NAMESPACE_
|
|
227
272
|
template<int Size, int Hashsize>
|
|
228
273
|
struct has_trivial_copy< HashObject<Size, Hashsize> > : true_type { };
|
|
229
274
|
|
|
230
275
|
template<int Size, int Hashsize>
|
|
231
276
|
struct has_trivial_destructor< HashObject<Size, Hashsize> > : true_type { };
|
|
277
|
+
|
|
232
278
|
_END_GOOGLE_NAMESPACE_
|
|
233
279
|
|
|
234
280
|
class HashFn {
|
|
@@ -237,12 +283,23 @@ class HashFn {
|
|
|
237
283
|
size_t operator()(const HashObject<Size,Hashsize>& obj) const {
|
|
238
284
|
return obj.Hash();
|
|
239
285
|
}
|
|
240
|
-
//
|
|
286
|
+
// Do the identity hash for pointers.
|
|
287
|
+
template<int Size, int Hashsize>
|
|
288
|
+
size_t operator()(const HashObject<Size,Hashsize>* obj) const {
|
|
289
|
+
return reinterpret_cast<uintptr_t>(obj);
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
// Less operator for MSVC's hash containers.
|
|
241
293
|
template<int Size, int Hashsize>
|
|
242
294
|
bool operator()(const HashObject<Size,Hashsize>& a,
|
|
243
295
|
const HashObject<Size,Hashsize>& b) const {
|
|
244
296
|
return a < b;
|
|
245
297
|
}
|
|
298
|
+
template<int Size, int Hashsize>
|
|
299
|
+
bool operator()(const HashObject<Size,Hashsize>* a,
|
|
300
|
+
const HashObject<Size,Hashsize>* b) const {
|
|
301
|
+
return a < b;
|
|
302
|
+
}
|
|
246
303
|
// These two public members are required by msvc. 4 and 8 are defaults.
|
|
247
304
|
static const size_t bucket_size = 4;
|
|
248
305
|
static const size_t min_buckets = 8;
|
|
@@ -260,7 +317,7 @@ class Rusage {
|
|
|
260
317
|
/* Reset collection */
|
|
261
318
|
void Reset();
|
|
262
319
|
|
|
263
|
-
/* Show usage */
|
|
320
|
+
/* Show usage, in seconds */
|
|
264
321
|
double UserTime();
|
|
265
322
|
|
|
266
323
|
private:
|
|
@@ -303,7 +360,6 @@ inline double Rusage::UserTime() {
|
|
|
303
360
|
#endif
|
|
304
361
|
}
|
|
305
362
|
|
|
306
|
-
|
|
307
363
|
static void print_uname() {
|
|
308
364
|
#ifdef HAVE_SYS_UTSNAME_H
|
|
309
365
|
struct utsname u;
|
|
@@ -326,9 +382,11 @@ static void stamp_run(int iters) {
|
|
|
326
382
|
printf("Current time (GMT): %s", asctime(gmtime(&now)));
|
|
327
383
|
}
|
|
328
384
|
|
|
329
|
-
//
|
|
330
|
-
//
|
|
331
|
-
//
|
|
385
|
+
// This depends on the malloc implementation for exactly what it does
|
|
386
|
+
// -- and thus requires work after the fact to make sense of the
|
|
387
|
+
// numbers -- and also is likely thrown off by the memory management
|
|
388
|
+
// STL tries to do on its own.
|
|
389
|
+
|
|
332
390
|
#ifdef HAVE_GOOGLE_MALLOC_EXTENSION_H
|
|
333
391
|
#include <google/malloc_extension.h>
|
|
334
392
|
|
|
@@ -370,7 +428,6 @@ static void time_map_grow(int iters) {
|
|
|
370
428
|
MapType set;
|
|
371
429
|
Rusage t;
|
|
372
430
|
|
|
373
|
-
SET_EMPTY_KEY(set, -2);
|
|
374
431
|
const size_t start = CurrentMemoryUsage();
|
|
375
432
|
t.Reset();
|
|
376
433
|
for (int i = 0; i < iters; i++) {
|
|
@@ -386,9 +443,8 @@ static void time_map_grow_predicted(int iters) {
|
|
|
386
443
|
MapType set;
|
|
387
444
|
Rusage t;
|
|
388
445
|
|
|
389
|
-
SET_EMPTY_KEY(set, -2);
|
|
390
446
|
const size_t start = CurrentMemoryUsage();
|
|
391
|
-
|
|
447
|
+
set.resize(iters);
|
|
392
448
|
t.Reset();
|
|
393
449
|
for (int i = 0; i < iters; i++) {
|
|
394
450
|
set[i] = i+1;
|
|
@@ -404,7 +460,6 @@ static void time_map_replace(int iters) {
|
|
|
404
460
|
Rusage t;
|
|
405
461
|
int i;
|
|
406
462
|
|
|
407
|
-
SET_EMPTY_KEY(set, -2);
|
|
408
463
|
for (i = 0; i < iters; i++) {
|
|
409
464
|
set[i] = i+1;
|
|
410
465
|
}
|
|
@@ -419,13 +474,13 @@ static void time_map_replace(int iters) {
|
|
|
419
474
|
}
|
|
420
475
|
|
|
421
476
|
template<class MapType>
|
|
422
|
-
static void time_map_fetch(int iters
|
|
477
|
+
static void time_map_fetch(int iters, const vector<int>& indices,
|
|
478
|
+
char const* title) {
|
|
423
479
|
MapType set;
|
|
424
480
|
Rusage t;
|
|
425
481
|
int r;
|
|
426
482
|
int i;
|
|
427
483
|
|
|
428
|
-
SET_EMPTY_KEY(set, -2);
|
|
429
484
|
for (i = 0; i < iters; i++) {
|
|
430
485
|
set[i] = i+1;
|
|
431
486
|
}
|
|
@@ -433,12 +488,39 @@ static void time_map_fetch(int iters) {
|
|
|
433
488
|
r = 1;
|
|
434
489
|
t.Reset();
|
|
435
490
|
for (i = 0; i < iters; i++) {
|
|
436
|
-
r ^= static_cast<int>(set.find(i) != set.end());
|
|
491
|
+
r ^= static_cast<int>(set.find(indices[i]) != set.end());
|
|
437
492
|
}
|
|
438
493
|
double ut = t.UserTime();
|
|
439
494
|
|
|
440
495
|
srand(r); // keep compiler from optimizing away r (we never call rand())
|
|
441
|
-
report(
|
|
496
|
+
report(title, ut, iters, 0, 0);
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
template<class MapType>
|
|
500
|
+
static void time_map_fetch_sequential(int iters) {
|
|
501
|
+
vector<int> v(iters);
|
|
502
|
+
for (int i = 0; i < iters; i++) {
|
|
503
|
+
v[i] = i;
|
|
504
|
+
}
|
|
505
|
+
time_map_fetch<MapType>(iters, v, "map_fetch_sequential");
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
// Apply a pseudorandom permutation to the given vector.
|
|
509
|
+
static void shuffle(vector<int>* v) {
|
|
510
|
+
srand(9);
|
|
511
|
+
for (int n = v->size(); n >= 2; n--) {
|
|
512
|
+
swap((*v)[n - 1], (*v)[static_cast<unsigned>(rand()) % n]);
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
template<class MapType>
|
|
517
|
+
static void time_map_fetch_random(int iters) {
|
|
518
|
+
vector<int> v(iters);
|
|
519
|
+
for (int i = 0; i < iters; i++) {
|
|
520
|
+
v[i] = i;
|
|
521
|
+
}
|
|
522
|
+
shuffle(&v);
|
|
523
|
+
time_map_fetch<MapType>(iters, v, "map_fetch_random");
|
|
442
524
|
}
|
|
443
525
|
|
|
444
526
|
template<class MapType>
|
|
@@ -448,7 +530,6 @@ static void time_map_fetch_empty(int iters) {
|
|
|
448
530
|
int r;
|
|
449
531
|
int i;
|
|
450
532
|
|
|
451
|
-
SET_EMPTY_KEY(set, -2);
|
|
452
533
|
r = 1;
|
|
453
534
|
t.Reset();
|
|
454
535
|
for (i = 0; i < iters; i++) {
|
|
@@ -466,13 +547,11 @@ static void time_map_remove(int iters) {
|
|
|
466
547
|
Rusage t;
|
|
467
548
|
int i;
|
|
468
549
|
|
|
469
|
-
SET_EMPTY_KEY(set, -2);
|
|
470
550
|
for (i = 0; i < iters; i++) {
|
|
471
551
|
set[i] = i+1;
|
|
472
552
|
}
|
|
473
553
|
|
|
474
554
|
t.Reset();
|
|
475
|
-
SET_DELETED_KEY(set, -1);
|
|
476
555
|
for (i = 0; i < iters; i++) {
|
|
477
556
|
set.erase(i);
|
|
478
557
|
}
|
|
@@ -489,8 +568,6 @@ static void time_map_toggle(int iters) {
|
|
|
489
568
|
|
|
490
569
|
const size_t start = CurrentMemoryUsage();
|
|
491
570
|
t.Reset();
|
|
492
|
-
SET_DELETED_KEY(set, -1);
|
|
493
|
-
SET_EMPTY_KEY(set, -2);
|
|
494
571
|
for (i = 0; i < iters; i++) {
|
|
495
572
|
set[i] = i+1;
|
|
496
573
|
set.erase(i);
|
|
@@ -503,40 +580,127 @@ static void time_map_toggle(int iters) {
|
|
|
503
580
|
}
|
|
504
581
|
|
|
505
582
|
template<class MapType>
|
|
506
|
-
static void
|
|
583
|
+
static void time_map_iterate(int iters) {
|
|
584
|
+
MapType set;
|
|
585
|
+
Rusage t;
|
|
586
|
+
int r;
|
|
587
|
+
int i;
|
|
588
|
+
|
|
589
|
+
for (i = 0; i < iters; i++) {
|
|
590
|
+
set[i] = i+1;
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
r = 1;
|
|
594
|
+
t.Reset();
|
|
595
|
+
for (typename MapType::const_iterator it = set.begin(), it_end = set.end();
|
|
596
|
+
it != it_end;
|
|
597
|
+
++it) {
|
|
598
|
+
r ^= it->second;
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
double ut = t.UserTime();
|
|
602
|
+
|
|
603
|
+
srand(r); // keep compiler from optimizing away r (we never call rand())
|
|
604
|
+
report("map_iterate", ut, iters, 0, 0);
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
template<class MapType>
|
|
608
|
+
static void stresshashfunction(int desired_insertions,
|
|
609
|
+
int map_size,
|
|
610
|
+
int stride) {
|
|
611
|
+
Rusage t;
|
|
612
|
+
int num_insertions = 0;
|
|
613
|
+
// One measurement of user time (in seconds) is done for each iteration of
|
|
614
|
+
// the outer loop. The times are summed.
|
|
615
|
+
double total_seconds = 0;
|
|
616
|
+
const int k = desired_insertions / map_size;
|
|
617
|
+
MapType set;
|
|
618
|
+
for (int o = 0; o < k; o++) {
|
|
619
|
+
set.clear();
|
|
620
|
+
set.resize(map_size);
|
|
621
|
+
t.Reset();
|
|
622
|
+
const int maxint = (1ull << (sizeof(int) * 8 - 1)) - 1;
|
|
623
|
+
// Use n arithmetic sequences. Using just one may lead to overflow
|
|
624
|
+
// if stride * map_size > maxint. Compute n by requiring
|
|
625
|
+
// stride * map_size/n < maxint, i.e., map_size/(maxint/stride) < n
|
|
626
|
+
char* key; // something we can do math on
|
|
627
|
+
const int n = map_size / (maxint / stride) + 1;
|
|
628
|
+
for (int i = 0; i < n; i++) {
|
|
629
|
+
key = NULL;
|
|
630
|
+
key += i;
|
|
631
|
+
for (int j = 0; j < map_size/n; j++) {
|
|
632
|
+
key += stride;
|
|
633
|
+
set[reinterpret_cast<typename MapType::key_type>(key)]
|
|
634
|
+
= ++num_insertions;
|
|
635
|
+
}
|
|
636
|
+
}
|
|
637
|
+
total_seconds += t.UserTime();
|
|
638
|
+
}
|
|
639
|
+
printf("stresshashfunction map_size=%d stride=%d: %.1fns/insertion\n",
|
|
640
|
+
map_size, stride, total_seconds * 1e9 / num_insertions);
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
template<class MapType>
|
|
644
|
+
static void stresshashfunction(int num_inserts) {
|
|
645
|
+
static const int kMapSizes[] = {256, 1024};
|
|
646
|
+
for (unsigned i = 0; i < sizeof(kMapSizes) / sizeof(kMapSizes[0]); i++) {
|
|
647
|
+
const int map_size = kMapSizes[i];
|
|
648
|
+
for (int stride = 1; stride <= map_size; stride *= map_size) {
|
|
649
|
+
stresshashfunction<MapType>(num_inserts, map_size, stride);
|
|
650
|
+
}
|
|
651
|
+
}
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
template<class MapType, class StressMapType>
|
|
655
|
+
static void measure_map(const char* label, int obj_size, int iters,
|
|
656
|
+
bool stress_hash_function) {
|
|
507
657
|
printf("\n%s (%d byte objects, %d iterations):\n", label, obj_size, iters);
|
|
508
658
|
if (1) time_map_grow<MapType>(iters);
|
|
509
659
|
if (1) time_map_grow_predicted<MapType>(iters);
|
|
510
660
|
if (1) time_map_replace<MapType>(iters);
|
|
511
|
-
if (1)
|
|
661
|
+
if (1) time_map_fetch_random<MapType>(iters);
|
|
662
|
+
if (1) time_map_fetch_sequential<MapType>(iters);
|
|
512
663
|
if (1) time_map_fetch_empty<MapType>(iters);
|
|
513
664
|
if (1) time_map_remove<MapType>(iters);
|
|
514
665
|
if (1) time_map_toggle<MapType>(iters);
|
|
666
|
+
if (1) time_map_iterate<MapType>(iters);
|
|
667
|
+
// This last test is useful only if the map type uses hashing.
|
|
668
|
+
// And it's slow, so use fewer iterations.
|
|
669
|
+
if (stress_hash_function) {
|
|
670
|
+
// Blank line in the output makes clear that what follows isn't part of the
|
|
671
|
+
// table of results that we just printed.
|
|
672
|
+
puts("");
|
|
673
|
+
stresshashfunction<StressMapType>(iters / 4);
|
|
674
|
+
}
|
|
515
675
|
}
|
|
516
676
|
|
|
517
677
|
template<class ObjType>
|
|
518
678
|
static void test_all_maps(int obj_size, int iters) {
|
|
679
|
+
const bool stress_hash_function = obj_size <= 8;
|
|
680
|
+
|
|
519
681
|
if (FLAGS_test_sparse_hash_map)
|
|
520
|
-
measure_map<
|
|
521
|
-
|
|
682
|
+
measure_map< EasyUseSparseHashMap<ObjType, int, HashFn>,
|
|
683
|
+
EasyUseSparseHashMap<ObjType*, int, HashFn> >(
|
|
684
|
+
"SPARSE_HASH_MAP", obj_size, iters, stress_hash_function);
|
|
685
|
+
|
|
522
686
|
if (FLAGS_test_dense_hash_map)
|
|
523
|
-
measure_map<
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
measure_map< HASH_NAMESPACE::unordered_map<ObjType, int, HashFn> >(
|
|
528
|
-
"TR1 UNORDERED_MAP", obj_size, iters);
|
|
529
|
-
#elif defined(HAVE_HASH_MAP)
|
|
687
|
+
measure_map< EasyUseDenseHashMap<ObjType, int, HashFn>,
|
|
688
|
+
EasyUseDenseHashMap<ObjType*, int, HashFn> >(
|
|
689
|
+
"DENSE_HASH_MAP", obj_size, iters, stress_hash_function);
|
|
690
|
+
|
|
530
691
|
if (FLAGS_test_hash_map)
|
|
531
|
-
measure_map<
|
|
532
|
-
|
|
533
|
-
|
|
692
|
+
measure_map< EasyUseHashMap<ObjType, int, HashFn>,
|
|
693
|
+
EasyUseHashMap<ObjType*, int, HashFn> >(
|
|
694
|
+
"STANDARD HASH_MAP", obj_size, iters, stress_hash_function);
|
|
695
|
+
|
|
534
696
|
if (FLAGS_test_map)
|
|
535
|
-
measure_map<
|
|
536
|
-
|
|
697
|
+
measure_map< EasyUseMap<ObjType, int>,
|
|
698
|
+
EasyUseMap<ObjType*, int> >(
|
|
699
|
+
"STANDARD MAP", obj_size, iters, false);
|
|
537
700
|
}
|
|
538
701
|
|
|
539
702
|
int main(int argc, char** argv) {
|
|
703
|
+
|
|
540
704
|
int iters = kDefaultIters;
|
|
541
705
|
if (argc > 1) { // first arg is # of iterations
|
|
542
706
|
iters = atoi(argv[1]);
|
|
@@ -555,6 +719,7 @@ int main(int argc, char** argv) {
|
|
|
555
719
|
// buffer. To keep memory use similar, we normalize the number of
|
|
556
720
|
// iterations based on size.
|
|
557
721
|
if (FLAGS_test_4_bytes) test_all_maps< HashObject<4,4> >(4, iters/1);
|
|
722
|
+
if (FLAGS_test_8_bytes) test_all_maps< HashObject<8,8> >(8, iters/2);
|
|
558
723
|
if (FLAGS_test_16_bytes) test_all_maps< HashObject<16,16> >(16, iters/4);
|
|
559
724
|
if (FLAGS_test_256_bytes) test_all_maps< HashObject<256,256> >(256, iters/32);
|
|
560
725
|
|