google_hash 0.8.1 → 0.8.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (121) hide show
  1. data/ChangeLog.txt +2 -0
  2. data/VERSION +1 -1
  3. data/ext/clean.bat +0 -0
  4. data/ext/clean.sh +4 -0
  5. data/ext/extconf.rb +4 -5
  6. data/ext/go.bat +0 -0
  7. data/ext/sparsehash-2.0.2/AUTHORS +2 -0
  8. data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/COPYING +0 -0
  9. data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/ChangeLog +60 -0
  10. data/ext/sparsehash-2.0.2/INSTALL +365 -0
  11. data/ext/sparsehash-2.0.2/Makefile +1336 -0
  12. data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/Makefile.am +97 -40
  13. data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/Makefile.in +538 -256
  14. data/ext/sparsehash-2.0.2/NEWS +188 -0
  15. data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/README +4 -10
  16. data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/README_windows.txt +3 -3
  17. data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/TODO +0 -0
  18. data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/aclocal.m4 +266 -166
  19. data/ext/sparsehash-2.0.2/allocator.patch +31 -0
  20. data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/config.guess +235 -234
  21. data/ext/sparsehash-2.0.2/config.status +1238 -0
  22. data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/config.sub +198 -64
  23. data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/configure +1118 -1000
  24. data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/configure.ac +4 -5
  25. data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/depcomp +136 -36
  26. data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/doc/dense_hash_map.html +182 -67
  27. data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/doc/dense_hash_set.html +173 -74
  28. data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/doc/designstyle.css +0 -6
  29. data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/doc/implementation.html +0 -0
  30. data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/doc/index.html +4 -5
  31. data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/doc/performance.html +1 -1
  32. data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/doc/sparse_hash_map.html +190 -58
  33. data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/doc/sparse_hash_set.html +180 -65
  34. data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/doc/sparsetable.html +1 -1
  35. data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/experimental/Makefile +0 -0
  36. data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/experimental/README +0 -0
  37. data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/experimental/example.c +1 -0
  38. data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/experimental/libchash.c +1 -0
  39. data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/experimental/libchash.h +1 -0
  40. data/ext/sparsehash-2.0.2/install-sh +520 -0
  41. data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/m4/acx_pthread.m4 +34 -0
  42. data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/m4/google_namespace.m4 +0 -0
  43. data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/m4/namespaces.m4 +0 -0
  44. data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/m4/stl_hash.m4 +0 -0
  45. data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/m4/stl_hash_fun.m4 +0 -0
  46. data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/missing +60 -44
  47. data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/packages/deb.sh +0 -0
  48. data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/packages/deb/README +0 -0
  49. data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/packages/deb/changelog +42 -0
  50. data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/packages/deb/compat +0 -0
  51. data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/packages/deb/control +1 -1
  52. data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/packages/deb/copyright +5 -4
  53. data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/packages/deb/docs +0 -0
  54. data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/packages/deb/rules +0 -0
  55. data/ext/sparsehash-2.0.2/packages/deb/sparsehash.dirs +5 -0
  56. data/ext/sparsehash-2.0.2/packages/deb/sparsehash.install +6 -0
  57. data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/packages/rpm.sh +1 -1
  58. data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/packages/rpm/rpm.spec +5 -3
  59. data/ext/{sparsehash-1.8.1/google-sparsehash.sln → sparsehash-2.0.2/sparsehash.sln} +0 -0
  60. data/ext/sparsehash-2.0.2/src/config.h +132 -0
  61. data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/src/config.h.in +0 -3
  62. data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/src/config.h.include +0 -1
  63. data/ext/sparsehash-2.0.2/src/google/dense_hash_map +34 -0
  64. data/ext/sparsehash-2.0.2/src/google/dense_hash_set +34 -0
  65. data/ext/sparsehash-2.0.2/src/google/sparse_hash_map +34 -0
  66. data/ext/sparsehash-2.0.2/src/google/sparse_hash_set +34 -0
  67. data/ext/sparsehash-2.0.2/src/google/sparsehash/densehashtable.h +34 -0
  68. data/ext/sparsehash-2.0.2/src/google/sparsehash/hashtable-common.h +34 -0
  69. data/ext/sparsehash-2.0.2/src/google/sparsehash/libc_allocator_with_realloc.h +34 -0
  70. data/ext/sparsehash-2.0.2/src/google/sparsehash/sparsehashtable.h +34 -0
  71. data/ext/sparsehash-2.0.2/src/google/sparsetable +34 -0
  72. data/ext/sparsehash-2.0.2/src/google/template_util.h +34 -0
  73. data/ext/sparsehash-2.0.2/src/google/type_traits.h +34 -0
  74. data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/src/hash_test_interface.h +64 -37
  75. data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/src/hashtable_test.cc +415 -141
  76. data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/src/libc_allocator_with_realloc_test.cc +16 -23
  77. data/ext/sparsehash-2.0.2/src/simple_compat_test.cc +106 -0
  78. data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/src/simple_test.cc +8 -5
  79. data/ext/{sparsehash-1.8.1/src/google → sparsehash-2.0.2/src/sparsehash}/dense_hash_map +80 -37
  80. data/ext/{sparsehash-1.8.1/src/google → sparsehash-2.0.2/src/sparsehash}/dense_hash_set +64 -34
  81. data/ext/{sparsehash-1.8.1/src/google/sparsehash → sparsehash-2.0.2/src/sparsehash/internal}/densehashtable.h +247 -173
  82. data/ext/sparsehash-2.0.2/src/sparsehash/internal/hashtable-common.h +381 -0
  83. data/ext/{sparsehash-1.8.1/src/google/sparsehash → sparsehash-2.0.2/src/sparsehash/internal}/libc_allocator_with_realloc.h +5 -7
  84. data/ext/{sparsehash-1.8.1/src/google/sparsehash → sparsehash-2.0.2/src/sparsehash/internal}/sparsehashtable.h +154 -93
  85. data/ext/{sparsehash-1.8.1/src/google → sparsehash-2.0.2/src/sparsehash}/sparse_hash_map +96 -36
  86. data/ext/{sparsehash-1.8.1/src/google → sparsehash-2.0.2/src/sparsehash}/sparse_hash_set +85 -32
  87. data/ext/{sparsehash-1.8.1/src/google → sparsehash-2.0.2/src/sparsehash}/sparsetable +520 -258
  88. data/ext/sparsehash-2.0.2/src/sparsehash/template_util.h +134 -0
  89. data/ext/{sparsehash-1.8.1/src/google → sparsehash-2.0.2/src/sparsehash}/type_traits.h +153 -35
  90. data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/src/sparsetable_unittest.cc +108 -22
  91. data/ext/sparsehash-2.0.2/src/stamp-h1 +1 -0
  92. data/ext/sparsehash-2.0.2/src/template_util_unittest.cc +134 -0
  93. data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/src/testutil.h +16 -1
  94. data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/src/time_hash_map.cc +259 -94
  95. data/ext/sparsehash-2.0.2/src/type_traits_unittest.cc +636 -0
  96. data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/src/windows/config.h +4 -4
  97. data/ext/sparsehash-2.0.2/src/windows/google/sparsehash/sparseconfig.h +49 -0
  98. data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/src/windows/port.cc +1 -0
  99. data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/src/windows/port.h +4 -13
  100. data/ext/sparsehash-2.0.2/src/windows/sparsehash/internal/sparseconfig.h +49 -0
  101. data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/vsprojects/hashtable_test/hashtable_test.vcproj +11 -11
  102. data/ext/sparsehash-2.0.2/vsprojects/libc_allocator_with_realloc_test/libc_allocator_with_realloc_test.vcproj +161 -0
  103. data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/vsprojects/simple_test/simple_test.vcproj +10 -10
  104. data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/vsprojects/sparsetable_unittest/sparsetable_unittest.vcproj +4 -4
  105. data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/vsprojects/time_hash_map/time_hash_map.vcproj +10 -10
  106. data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/vsprojects/type_traits_unittest/type_traits_unittest.vcproj +3 -3
  107. data/ext/spec.bat +0 -0
  108. data/ext/template/google_hash.cpp.erb +6 -5
  109. metadata +106 -86
  110. data/ext/sparsehash-1.8.1/AUTHORS +0 -2
  111. data/ext/sparsehash-1.8.1/INSTALL +0 -236
  112. data/ext/sparsehash-1.8.1/NEWS +0 -71
  113. data/ext/sparsehash-1.8.1/compile +0 -99
  114. data/ext/sparsehash-1.8.1/install-sh +0 -323
  115. data/ext/sparsehash-1.8.1/m4/stl_namespace.m4 +0 -25
  116. data/ext/sparsehash-1.8.1/mkinstalldirs +0 -158
  117. data/ext/sparsehash-1.8.1/packages/deb/sparsehash.dirs +0 -2
  118. data/ext/sparsehash-1.8.1/packages/deb/sparsehash.install +0 -2
  119. data/ext/sparsehash-1.8.1/src/google/sparsehash/hashtable-common.h +0 -178
  120. data/ext/sparsehash-1.8.1/src/type_traits_unittest.cc +0 -502
  121. 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 "config.h"
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> // for uname()
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 <google/type_traits.h>
71
-
72
- #include <google/sparse_hash_map>
73
- using GOOGLE_NAMESPACE::sparse_hash_map;
74
-
75
- #include <google/dense_hash_map>
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
- // Normally I don't like non-const references, but using them here ensures
91
- // the inlined code ends up as efficient as possible.
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
- // These are operations that are supported on some hash impls but not others
94
- template<class MapType> inline void SET_DELETED_KEY(MapType&, int /*key*/) {}
95
- template<class MapType> inline void SET_EMPTY_KEY(MapType&, int /*key*/) {}
96
- template<class MapType> inline void RESIZE(MapType&, int /*iters*/) {}
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<class K, class V, class H, class E, class A>
99
- inline void SET_DELETED_KEY(sparse_hash_map<K,V,H,E,A>& m, int key) {
100
- m.set_deleted_key(key);
101
- }
102
- template<class K, class V, class H, class E, class A>
103
- inline void SET_DELETED_KEY(dense_hash_map<K,V,H,E,A>& m, int key) {
104
- m.set_deleted_key(key);
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
- template<class K, class V, class H, class E, class A>
108
- inline void SET_EMPTY_KEY(dense_hash_map<K,V,H,E,A>& m, int key) {
109
- m.set_empty_key(key);
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<class K, class V, class H, class E, class A>
122
- inline void RESIZE(HASH_NAMESPACE::unordered_map<K,V,H,E,A>& m, int iters) {
123
- m.rehash(iters); // the tr1 name for resize()
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
- // MSVC/Dinkumware hash impl has fewer template args, and no resize support.
127
- template<class K, class V, class H, class A>
128
- inline void RESIZE(HASH_NAMESPACE::hash_map<K,V,H,A>& m, int iters) {
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<class K, class V, class H, class E, class A>
132
- inline void RESIZE(HASH_NAMESPACE::hash_map<K,V,H,E,A>& m, int iters) {
133
- m.resize(iters);
134
- }
135
- #endif // HAVE_HASH_MAP
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); // defined in sparseconfig.h
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
- // For windows
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
- // If you have google-perftools (http://code.google.com/p/google-perftools),
330
- // then you can figure out how much memory these implementations use
331
- // as well.
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
- RESIZE(set, iters);
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("map_fetch", ut, iters, 0, 0);
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 measure_map(const char* label, int obj_size, int iters) {
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) time_map_fetch<MapType>(iters);
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< sparse_hash_map<ObjType, int, HashFn> >("SPARSE_HASH_MAP",
521
- obj_size, iters);
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< dense_hash_map<ObjType, int, HashFn> >("DENSE_HASH_MAP",
524
- obj_size, iters);
525
- #if defined(HAVE_UNORDERED_MAP)
526
- if (FLAGS_test_hash_map)
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< HASH_NAMESPACE::hash_map<ObjType, int, HashFn> >(
532
- "STANDARD HASH_MAP", obj_size, iters);
533
- #endif
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< STL_NAMESPACE::map<ObjType, int, HashFn> >("STANDARD MAP",
536
- obj_size, iters);
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