dbms: development [#CONV-2944].

This commit is contained in:
Alexey Milovidov 2011-12-19 04:26:27 +00:00
parent 1197d447c4
commit 321475d215
3 changed files with 62 additions and 28 deletions

View File

@ -9,6 +9,8 @@
#include <Yandex/optimization.h>
#include <DB/Core/Types.h>
namespace DB
{
@ -65,8 +67,8 @@ private:
size_t m_size; /// Количество элементов
UInt8 size_degree; /// Размер таблицы в виде степени двух
bool has_zero; /// Хэш-таблица содержит элемент со значением ключа = 0.
Value zero_value;
Value * buf;
Value * buf; /// Кусок памяти для всех элементов кроме элемента с ключём 0.
char zero_value_storage[sizeof(Value)]; /// Кусок памяти для элемента с ключём 0.
Hash hash;
@ -76,6 +78,8 @@ private:
inline size_t mask() const { return buf_size() - 1; }
inline size_t place(HashValue x) const { return x & mask(); }
inline Value * zero_value() { return reinterpret_cast<Value*>(zero_value_storage); }
/// Увеличить размер буфера в 2 ^ GROWTH_DEGREE раз
void resize()
@ -123,7 +127,7 @@ public:
size_degree(INITIAL_SIZE_DEGREE),
has_zero(false)
{
ZeroTraits::set(zero_value.first);
ZeroTraits::set(zero_value()->first);
buf = reinterpret_cast<Value*>(calloc(buf_size(), sizeof(Value)));
}
@ -205,7 +209,7 @@ public:
const_iterator begin() const
{
if (has_zero)
return const_iterator(this, &zero_value);
return const_iterator(this, zero_value());
const Value * ptr = buf;
while (ZeroTraits::check(ptr->first) && ptr < buf + buf_size())
@ -217,7 +221,7 @@ public:
iterator begin()
{
if (has_zero)
return iterator(this, &zero_value);
return iterator(this, zero_value());
Value * ptr = buf;
while (ZeroTraits::check(ptr->first) && ptr < buf + buf_size())
@ -239,7 +243,7 @@ public:
{
++m_size;
has_zero = true;
zero_value.second = x.second;
zero_value()->second = x.second;
return std::make_pair(begin(), true);
}
return std::make_pair(begin(), false);
@ -256,7 +260,7 @@ public:
iterator res(this, &buf[place_value]);
if (buf[place_value].first == x.first)
if (!ZeroTraits::check(buf[place_value].first) && buf[place_value].first == x.first)
return std::make_pair(res, false);
buf[place_value] = x;
@ -276,6 +280,9 @@ public:
* вернуть итератор на позицию, которую можно использовать для placement new значения,
* а также флаг - был ли вставлен новый ключ.
*
* Вы обязаны сделать placement new значения, если был вставлен новый ключ,
* так как при уничтожении хэш-таблицы для него будет вызываться деструктор!
*
* Пример использования:
*
* Map::iterator it;
@ -288,8 +295,6 @@ public:
{
if (ZeroTraits::check(x))
{
it = begin();
if (!has_zero)
{
++m_size;
@ -298,7 +303,8 @@ public:
}
else
inserted = false;
it = begin();
return;
}
@ -313,13 +319,13 @@ public:
it = iterator(this, &buf[place_value]);
if (buf[place_value].first == x)
if (!ZeroTraits::check(buf[place_value].first) && buf[place_value].first == x)
{
inserted = false;
return;
}
buf[place_value].first = x;
new(&buf[place_value].first) Key(x);
inserted = true;
++m_size;

View File

@ -43,9 +43,8 @@ int main(int argc, char ** argv)
for (size_t i = 0; i < n; ++i)
data[i] = rand() % m;
for (size_t i = 0; i < n; ++i)
if (data[i] == 0)
data[i] = 1;
for (size_t i = 0; i < n; i += 10)
data[i] = 0;
watch.stop();
std::cerr << std::fixed << std::setprecision(2)
@ -96,7 +95,7 @@ int main(int argc, char ** argv)
Stopwatch watch;
google::dense_hash_map<Key, Value> map;
map.set_empty_key(0);
map.set_empty_key(-1ULL);
for (size_t i = 0; i < n; ++i)
map.insert(std::make_pair(data[i], value));

View File

@ -32,21 +32,50 @@
#include <DB/DataTypes/DataTypesNumberFixed.h>
struct StringZeroTraits
struct SimpleString
{
static char empty[sizeof(std::string)];
char * data;
static inline bool check(const std::string & x) { return 0 == memcmp(&x, &empty, sizeof(x)); }
static inline void set(std::string & x) { memset(&x, 0, sizeof(x)); }
SimpleString() : data(NULL) {}
SimpleString(const std::string & s)
{
data = reinterpret_cast<char *>(malloc(s.size()));
memcpy(data, s.data(), s.size());
}
SimpleString(const SimpleString & s)
{
/// move
data = s.data;
const_cast<char *&>(s.data) = NULL;
}
~SimpleString()
{
free(data);
}
bool operator== (const SimpleString & s)
{
return 0 == strcmp(data, s.data);
}
bool operator!= (const SimpleString & s)
{
return !operator==(s);
}
};
char StringZeroTraits::empty[sizeof(std::string)];
/// Немного быстрее стандартного
struct StringHash
struct SimpleStringZeroTraits
{
size_t operator()(const std::string & x) const { return CityHash64(x.data(), x.size()); }
static inline bool check(const SimpleString & x) { return 0 == x.data; }
static inline void set(SimpleString & x) { x.data = 0; }
};
struct SimpleStringHash
{
size_t operator()(const SimpleString & x) const { return CityHash64(x.data, strlen(x.data)); }
};
@ -60,7 +89,7 @@ int main(int argc, char ** argv)
DB::DataTypes data_types_uint64;
data_types_uint64.push_back(new DB::DataTypeUInt64);
size_t n = 100000;
size_t n = 1000000;
std::vector<Key> data(n);
Value value;
@ -90,7 +119,7 @@ int main(int argc, char ** argv)
{
Stopwatch watch;
typedef DB::HashMap<Key, Value, StringHash, StringZeroTraits> Map;
typedef DB::HashMap<SimpleString, Value, SimpleStringHash, SimpleStringZeroTraits> Map;
Map map;
Map::iterator it;
bool inserted;