#define GOOGLE_NAMESPACE google
#define HASH_FUN_H <ext/hash_fun.h>
#define HASH_MAP_H <ext/hash_map>
#define UNORDERED_MAP_H <tr1/unordered_map>
#define HASH_NAMESPACE __gnu_cxx
#define TR1_NAMESPACE std::tr1
#define HASH_SET_H <ext/hash_set>
#define HAVE_GOOGLE_MALLOC_EXTENSION_H 1
#define HAVE_HASH_MAP 1
#define HAVE_HASH_SET 1
#define HAVE_UNORDERED_MAP 1
#define HAVE_INTTYPES_H 1
#define HAVE_LONG_LONG 1
#define HAVE_MEMCPY 1
#define HAVE_MEMMOVE 1
#define HAVE_MEMORY_H 1
#define HAVE_NAMESPACES 1
#define HAVE_STDINT_H 1
#define HAVE_STDLIB_H 1
#define HAVE_STRINGS_H 1
#define HAVE_STRING_H 1
#define HAVE_SYS_RESOURCE_H 1
#define HAVE_SYS_STAT_H 1
#define HAVE_SYS_TIME_H 1
#define HAVE_SYS_TYPES_H 1
#define HAVE_SYS_UTSNAME_H 1
#define HAVE_UINT16_T 1
#define HAVE_UNISTD_H 1
#define HAVE_U_INT16_T 1
#define PACKAGE "sparsehash"
#define PACKAGE_BUGREPORT "opensource@google.com"
#define PACKAGE_NAME "sparsehash"
#define PACKAGE_STRING "sparsehash 1.1"
#define PACKAGE_TARNAME "sparsehash"
#define PACKAGE_VERSION "1.1"
#define SPARSEHASH_HASH HASH_NAMESPACE::hash
#define SPARSEHASH_HASH_NO_NAMESPACE hash
#define STDC_HEADERS 1
#define STL_NAMESPACE std
#define VERSION "1.1"
#define _END_GOOGLE_NAMESPACE_ }
#define _START_GOOGLE_NAMESPACE_ namespace google {
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
extern "C" {
#include <time.h>
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#endif
#ifdef HAVE_SYS_RESOURCE_H
#include <sys/resource.h>
#endif
#ifdef HAVE_SYS_UTSNAME_H
#include <sys/utsname.h> #endif
#ifdef HAVE_WINDOWS_H
#include <Windows.h> #endif
}
#include <map>
#include <google/type_traits.h>
#include "khash.hh"
using STL_NAMESPACE::map;
#include <google/sparse_hash_map>
using GOOGLE_NAMESPACE::sparse_hash_map;
#include <google/dense_hash_map>
using GOOGLE_NAMESPACE::dense_hash_map;
#ifdef HAVE_HASH_MAP #include HASH_MAP_H using HASH_NAMESPACE::hash_map;
#endif
#ifdef HAVE_UNORDERED_MAP
#include UNORDERED_MAP_H
using TR1_NAMESPACE::unordered_map;
#endif
static const int kDefaultIters = 10000000;
template<class MapType> inline void SET_DELETED_KEY(MapType& m, int key) {}
template<class MapType> inline void SET_EMPTY_KEY(MapType& m, int key) {}
template<class MapType> inline void RESIZE(MapType& m, int iters) {}
template<class K, class V> inline void SET_DELETED_KEY(sparse_hash_map<K,V>& m,
int key) {
m.set_deleted_key(key);
}
template<class K, class V> inline void SET_DELETED_KEY(dense_hash_map<K,V>& m,
int key) {
m.set_deleted_key(key);
}
template<class K, class V> inline void SET_EMPTY_KEY(dense_hash_map<K,V>& m,
int key) {
m.set_empty_key(key);
}
template<class K, class V> inline void RESIZE(sparse_hash_map<K,V>& m,
int iters) {
m.resize(iters);
}
template<class K, class V> inline void RESIZE(dense_hash_map<K,V>& m,
int iters) {
m.resize(iters);
}
template<class K, class V> inline void RESIZE(hash_map<K,V>& m,
int iters) {
#ifndef WIN32
m.resize(iters);
#endif
}
class Rusage {
public:
Rusage() { Reset(); }
void Reset();
double UserTime();
private:
#if defined HAVE_SYS_RESOURCE_H
struct rusage start;
#elif defined HAVE_WINDOWS_H
long long int start;
#else
time_t start_time_t;
#endif
};
inline void Rusage::Reset() {
#if defined HAVE_SYS_RESOURCE_H
getrusage(RUSAGE_SELF, &start);
#elif defined HAVE_WINDOWS_H
start = GetTickCount();
#else
time(&start_time_t);
#endif
}
inline double Rusage::UserTime() {
#if defined HAVE_SYS_RESOURCE_H
struct rusage u;
getrusage(RUSAGE_SELF, &u);
struct timeval result;
result.tv_sec = u.ru_utime.tv_sec - start.ru_utime.tv_sec;
result.tv_usec = u.ru_utime.tv_usec - start.ru_utime.tv_usec;
return double(result.tv_sec) + double(result.tv_usec) / 1000000.0;
#elif defined HAVE_WINDOWS_H
return double(GetTickCount() - start) / 1000.0;
#else
time_t now;
time(&now);
return now - start_time_t;
#endif
}
static void print_uname() {
#ifdef HAVE_SYS_UTSNAME_H
struct utsname u;
if (uname(&u) == 0) {
printf("%s %s %s %s %s\n",
u.sysname, u.nodename, u.release, u.version, u.machine);
}
#endif
}
static void stamp_run(int iters) {
time_t now = time(0);
printf("======\n");
fflush(stdout);
print_uname();
printf("Average over %d iterations\n", iters);
fflush(stdout);
printf("Current time (GMT): %s", asctime(gmtime(&now)));
}
#ifdef HAVE_GOOGLE_MALLOC_EXTENSION_H
#include <google/malloc_extension.h>
static size_t CurrentMemoryUsage() {
size_t result;
if (MallocExtension::instance()->GetNumericProperty(
"generic.current_allocated_bytes",
&result)) {
return result;
} else {
return 0;
}
}
#else
static size_t CurrentMemoryUsage() { return 0; }
#endif
static void report(char const* title, double t,
int iters,
size_t heap_growth) {
char heap[100];
if (heap_growth > 0) {
snprintf(heap, sizeof(heap), "%8.1f MB", heap_growth / 1048576.0);
} else {
heap[0] = '\0';
}
printf("%-20s %8.1f ns %s\n", title, (t * 1000000000.0 / iters), heap);
fflush(stdout);
}
template<class MapType>
static void time_map_grow(int iters) {
MapType set;
Rusage t;
SET_EMPTY_KEY(set, -2);
const size_t start = CurrentMemoryUsage();
t.Reset();
for (int i = 0; i < iters; i++) {
set[i] = i+1;
}
double ut = t.UserTime();
const size_t finish = CurrentMemoryUsage();
report("map_grow", ut, iters, finish - start);
}
template<class MapType>
static void time_map_grow_predicted(int iters) {
MapType set;
Rusage t;
SET_EMPTY_KEY(set, -2);
const size_t start = CurrentMemoryUsage();
RESIZE(set, iters);
t.Reset();
for (int i = 0; i < iters; i++) {
set[i] = i+1;
}
double ut = t.UserTime();
const size_t finish = CurrentMemoryUsage();
report("map_predict/grow", ut, iters, finish - start);
}
template<class MapType>
static void time_map_replace(int iters) {
MapType set;
Rusage t;
int i;
SET_EMPTY_KEY(set, -2);
for (i = 0; i < iters; i++) {
set[i] = i+1;
}
t.Reset();
for (i = 0; i < iters; i++) {
set[i] = i+1;
}
double ut = t.UserTime();
report("map_replace", ut, iters, 0);
}
template<class MapType>
static void time_map_fetch(int iters) {
MapType set;
Rusage t;
int r;
int i;
SET_EMPTY_KEY(set, -2);
for (i = 0; i < iters; i++) {
set[i] = i+1;
}
r = 1;
t.Reset();
for (i = 0; i < iters; i++) {
r ^= static_cast<int>(set.find(i) != set.end());
}
double ut = t.UserTime();
srand(r); report("map_fetch", ut, iters, 0);
}
template<class MapType>
static void time_map_fetch_empty(int iters) {
MapType set;
Rusage t;
int r;
int i;
SET_EMPTY_KEY(set, -2);
r = 1;
t.Reset();
for (i = 0; i < iters; i++) {
r ^= static_cast<int>(set.find(i) != set.end());
}
double ut = t.UserTime();
srand(r); report("map_fetch_empty", ut, iters, 0);
}
template<class MapType>
static void time_map_remove(int iters) {
MapType set;
Rusage t;
int i;
SET_EMPTY_KEY(set, -2);
for (i = 0; i < iters; i++) {
set[i] = i+1;
}
t.Reset();
SET_DELETED_KEY(set, -1);
for (i = 0; i < iters; i++) {
set.erase(i);
}
double ut = t.UserTime();
report("map_remove", ut, iters, 0);
}
template<class MapType>
static void measure_map(const char* label, int iters) {
printf("\n%s:\n", label);
if (1) time_map_grow<MapType>(iters);
if (1) time_map_grow_predicted<MapType>(iters);
if (1) time_map_replace<MapType>(iters);
if (1) time_map_fetch<MapType>(iters);
if (1) time_map_fetch_empty<MapType>(iters);
if (1) time_map_remove<MapType>(iters);
}
int main(int argc, char** argv) {
int iters = kDefaultIters;
if (argc > 1) { iters = atoi(argv[1]);
}
const int obj_size = 4;
const int hash_size = 4;
stamp_run(iters);
#ifndef HAVE_SYS_RESOURCE_H
printf("\n*** WARNING ***: sys/resources.h was not found, so all times\n"
" reported are wall-clock time, not user time\n");
#endif
if (1) measure_map< khmap_t<int, int> >("KHASH_MAP", iters);
if (1) measure_map< sparse_hash_map<int, int> >("SPARSE_HASH_MAP", iters);
if (1) measure_map< dense_hash_map<int, int> >("DENSE_HASH_MAP", iters);
#ifdef HAVE_HASH_MAP
if (1) measure_map< hash_map<int, int> >("STANDARD HASH_MAP", iters);
#endif
#ifdef HAVE_UNORDERED_MAP
if (1) measure_map< unordered_map<int, int> >("TR1 UNORDERED_MAP", iters);
#endif
if (1) measure_map< map<int, int> >("STANDARD MAP", iters);
return 0;
}