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