open_toontown_panda3d/panda/src/testbed/test_map.cxx

172 lines
4.2 KiB
C++

// Filename: test_map.cxx
// Created by: drose (29Sep04)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
#include "pandabase.h"
#include "pmap.h"
#include "memoryUsage.h"
#include "clockObject.h"
class Alpha {
public:
Alpha(const string &str) : _str(str) { }
size_t get_hash() const {
size_t hash = 0;
string::const_iterator si;
for (si = _str.begin(); si != _str.end(); ++si) {
hash = (hash * 31) + (size_t)(*si);
}
return hash;
}
bool operator < (const Alpha &other) const {
return strcmp(_str.c_str(), other._str.c_str()) < 0;
}
string _str;
};
ostream &operator << (ostream &out, const Alpha &alpha) {
return out << alpha._str;
}
class Beta : public Alpha {
public:
Beta(const string &str) : Alpha(str) { }
size_t get_hash() const {
return ~_str[0];
}
};
static const char * const sample_strings[] = {
"apple",
"apricot",
"banana",
"blueberry",
"grape",
"grapefruit",
"guava",
"honeydew",
"lemon",
"lime",
"mango",
"orange",
"peach",
"pear",
"pineapple",
"plum",
"raspberry",
"strawberry",
"watermelon",
};
static const size_t num_sample_strings = sizeof(sample_strings) / sizeof(const char *);
void
insert_fruit() {
// typedef pmap<Alpha, string> MapType;
// typedef pmap<Beta, string> MapType;
// typedef phash_map<Alpha, string> MapType;
typedef phash_map<Beta, string> MapType;
MapType m;
for (size_t i = 0; i < num_sample_strings; i++) {
string str = sample_strings[i];
bool inserted = m.insert(MapType::value_type(str, str)).second;
if (!inserted) {
cerr << "Could not insert " << str << "\n";
}
}
cout << "Map contains:\n";
MapType::iterator mi;
for (mi = m.begin(); mi != m.end(); ++mi) {
cout << " " << (*mi).first << "\n";
}
}
void
test_performance() {
typedef Alpha KeyType;
typedef phash_map<KeyType, int> MapType;
//typedef pmap<KeyType, int> MapType;
MemoryUsage::is_tracking();
ClockObject *clock = ClockObject::get_global_clock();
static const int key_len = 10;
static const int sample_mask = 0xffff;
static const int sample_size = sample_mask + 1;
static const int initial_population = 1000;
static const int num_cycles = 10000;
static const int num_reps = 3;
vector<KeyType> samples;
samples.reserve(sample_size);
for (int s = 0; s < sample_size; s++) {
string key;
for (int k = 0; k < key_len; k++) {
key += string(1, (char)((rand() & 0x3f) + '@'));
}
samples.push_back(key);
}
MemoryUsage::freeze();
MapType *m = new MapType;
if (MemoryUsage::has_cpp_size()) {
cerr << "Empty map uses " << MemoryUsage::get_current_cpp_size()
<< " bytes.\n";
}
for (int p = 0; p < initial_population; p++) {
m->insert(MapType::value_type(samples[rand() & sample_mask], 0));
}
if (MemoryUsage::has_cpp_size()) {
cerr << "map with " << m->size()
<< " elements uses " << MemoryUsage::get_current_cpp_size()
<< " bytes.\n";
}
for (int r = 0; r < num_reps; r++) {
double now = clock->get_real_time();
for (int c = 0; c < num_cycles; c++) {
const KeyType &element = samples[rand() & sample_mask];
bool inserted = m->insert(MapType::value_type(element, 0)).second;
if (inserted) {
m->erase(element);
}
}
double elapsed = clock->get_real_time() - now;
cerr << "After " << num_cycles << " cycles in " << elapsed * 1000.0
<< " ms, map has " << m->size()
<< " elements and uses " << MemoryUsage::get_current_cpp_size()
<< " bytes.\n";
}
}
int
main(int argc, char *argv[]) {
// insert_fruit();
test_performance();
return 0;
}