source: GTP/trunk/Lib/Vis/Preprocessing/src/sparsehash/src/time_hash_map.cc @ 2162

Revision 2162, 7.6 KB checked in by mattausch, 17 years ago (diff)

improved hash performance with google hashmap

Line 
1// Copyright (c) 2005, Google Inc.
2// All rights reserved.
3//
4// Redistribution and use in source and binary forms, with or without
5// modification, are permitted provided that the following conditions are
6// met:
7//
8//     * Redistributions of source code must retain the above copyright
9// notice, this list of conditions and the following disclaimer.
10//     * Redistributions in binary form must reproduce the above
11// copyright notice, this list of conditions and the following disclaimer
12// in the documentation and/or other materials provided with the
13// distribution.
14//     * Neither the name of Google Inc. nor the names of its
15// contributors may be used to endorse or promote products derived from
16// this software without specific prior written permission.
17//
18// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
30// ---
31// Authors: Sanjay Ghemawat and Craig Silverstein
32//
33// Time various hash map implementations
34//
35// See PERFORMANCE for the output of one example run.
36
37#include <google/sparsehash/config.h>
38#include <stdio.h>
39#include <stdlib.h>
40#include <string.h>
41extern "C" {
42#include <time.h>
43#ifdef HAVE_SYS_TIME_H
44#include <sys/time.h>
45#endif
46#ifdef HAVE_SYS_RESOURCE_H
47#include <sys/resource.h>
48#endif
49#ifdef HAVE_SYS_UTSNAME_H
50#include <sys/utsname.h>      // for uname()
51#endif
52}
53
54// The functions that we call on each map, that differ for different types.
55// By default each is a noop, but we redefine them for types that need them.
56
57#include <map>
58#include "hash_map.h"
59#include <google/sparse_hash_map>
60#include <google/dense_hash_map>
61
62using GOOGLE_NAMESPACE::sparse_hash_map;
63using GOOGLE_NAMESPACE::dense_hash_map;
64using HASH_NAMESPACE::hash_map;
65using STL_NAMESPACE::map;
66
67// Normally I don't like non-const references, but using them here ensures
68// the inlined code ends up as efficient as possible.
69
70template<class MapType> inline void SET_DELETED_KEY(MapType& map, int key) {}
71template<class MapType> inline void SET_EMPTY_KEY(MapType& map, int key) {}
72template<class MapType> inline void RESIZE(MapType& map, int iters) {}
73
74template<> inline void SET_DELETED_KEY(sparse_hash_map<int, int>& m, int key) {
75  m.set_deleted_key(key);
76}
77template<> inline void SET_DELETED_KEY(dense_hash_map<int, int>& m, int key) {
78  m.set_deleted_key(key);
79}
80
81template<> inline void SET_EMPTY_KEY(dense_hash_map<int, int>& m, int key) {
82  m.set_empty_key(key);
83}
84
85template<> inline void RESIZE(sparse_hash_map<int, int>& m, int iters) {
86  m.resize(iters);
87}
88template<> inline void RESIZE(dense_hash_map<int, int>& m, int iters) {
89  m.resize(iters);
90}
91#ifndef WIN32
92template<> inline void RESIZE(hash_map<int, int>& m, int iters) {
93  m.resize(iters);
94}
95#endif
96
97static const int default_iters = 10000000;
98
99
100/*
101 * Measure resource usage.
102 */
103
104class Rusage {
105 public:
106  /* Start collecting usage */
107  Rusage() { Reset(); }
108
109  /* Reset collection */
110  void Reset();
111   
112  /* Show usage */
113  double UserTime();
114
115 private:
116#ifdef HAVE_SYS_RESOURCE_H
117  struct rusage start;
118#else
119  time_t start_time_t;
120#endif
121};
122
123inline void Rusage::Reset() {
124#ifdef HAVE_SYS_RESOURCE_H
125  getrusage(RUSAGE_SELF, &start);
126#else
127  time(&start_time_t);
128#endif
129}
130
131inline double Rusage::UserTime() {
132#ifdef HAVE_SYS_RESOURCE_H
133  struct rusage u;
134 
135  getrusage(RUSAGE_SELF, &u);
136 
137  struct timeval result;
138  result.tv_sec  = u.ru_utime.tv_sec  - start.ru_utime.tv_sec;
139  result.tv_usec = u.ru_utime.tv_usec - start.ru_utime.tv_usec;
140 
141  return double(result.tv_sec) + double(result.tv_usec) / 1000000.0;
142#else
143  time_t now;
144  time(&now);
145  return now - start_time_t;
146#endif
147}
148
149
150static void print_uname() {
151#ifdef HAVE_SYS_UTSNAME_H
152  struct utsname u;
153  if (uname(&u) == 0) {
154    printf("%s %s %s %s %s\n",
155           u.sysname, u.nodename, u.release, u.version, u.machine);
156  }
157#endif
158}
159
160// Generate stamp for this run
161static void stamp_run(int iters) {
162  time_t now = time(0);
163  printf("======\n");
164  fflush(stdout);
165  print_uname();
166  printf("Average over %d iterations\n", iters);
167  fflush(stdout);
168  // don't need asctime_r/gmtime_r: we're not threaded
169  printf("Current time (GMT): %s", asctime(gmtime(&now)));
170}
171
172
173static void report(char const* title, double t, int iters) {
174  printf("%-20s %8.02f ns\n",
175         title,
176         (t * 1000000000.0 / iters));
177}
178
179template<class MapType>
180static void time_map_grow(int iters) {
181  MapType set;
182  Rusage t;
183
184  SET_EMPTY_KEY(set, -2);
185  t.Reset();
186  for (int i = 0; i < iters; i++) {
187    set[i] = i+1;
188  }
189  double ut = t.UserTime();
190
191  report("map_grow", ut, iters);
192}
193
194template<class MapType>
195static void time_map_grow_predicted(int iters) {
196  MapType set;
197  Rusage t;
198
199  SET_EMPTY_KEY(set, -2);
200  RESIZE(set, iters);
201  t.Reset();
202  for (int i = 0; i < iters; i++) {
203    set[i] = i+1;
204  }
205  double ut = t.UserTime();
206
207  report("map_predict/grow", ut, iters);
208}
209
210template<class MapType>
211static void time_map_replace(int iters) {
212  MapType set;
213  Rusage t;
214  int i;
215
216  SET_EMPTY_KEY(set, -2);
217  for (i = 0; i < iters; i++) {
218    set[i] = i+1;
219  }
220
221  t.Reset();
222  for (i = 0; i < iters; i++) {
223    set[i] = i+1;
224  }
225  double ut = t.UserTime();
226
227  report("map_replace", ut, iters);
228}
229
230template<class MapType>
231static void time_map_fetch(int iters) {
232  MapType set;
233  Rusage t;
234  int r;
235  int i;
236
237  SET_EMPTY_KEY(set, -2);
238  for (i = 0; i < iters; i++) {
239    set[i] = i+1;
240  }
241
242  r = 1;
243  t.Reset();
244  for (i = 0; i < iters; i++) {
245    r ^= (set.find(i) != set.end());
246  }
247  double ut = t.UserTime();
248
249  report("map_fetch", ut, iters);
250}
251
252template<class MapType>
253static void time_map_remove(int iters) {
254  MapType set;
255  Rusage t;
256  int i;
257
258  SET_EMPTY_KEY(set, -2);
259  for (i = 0; i < iters; i++) {
260    set[i] = i+1;
261  }
262
263  t.Reset();
264  SET_DELETED_KEY(set, -1);
265  for (i = 0; i < iters; i++) {
266    set.erase(i);
267  }
268  double ut = t.UserTime();
269
270  report("map_remove", ut, iters);
271}
272
273template<class MapType>
274static void measure_map(int iters) {
275  time_map_grow<MapType>(iters);
276  time_map_grow_predicted<MapType>(iters);
277  time_map_replace<MapType>(iters);
278  time_map_fetch<MapType>(iters);
279  time_map_remove<MapType>(iters);
280}
281
282int main(int argc, char** argv) {
283  int iters = default_iters;
284  if (argc > 1) {            // first arg is # of iterations
285    iters = atoi(argv[1]);
286  }
287
288  stamp_run(iters);
289
290#ifndef HAVE_SYS_RESOURCE_H
291  printf("\n*** WARNING ***: sys/resources.h was not found, so all times\n"
292         "                 reported are wall-clock time, not user time\n");
293#endif
294
295  printf("\nSPARSE_HASH_MAP:\n");
296  measure_map< sparse_hash_map<int, int> >(iters);
297
298  printf("\nDENSE_HASH_MAP:\n");
299  measure_map< dense_hash_map<int, int> >(iters);
300
301  printf("\nSTANDARD HASH_MAP:\n");
302  measure_map< hash_map<int, int> >(iters);
303
304  printf("\nSTANDARD MAP:\n");
305  measure_map< map<int, int> >(iters);
306
307  return 0;
308}
Note: See TracBrowser for help on using the repository browser.