mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-10 09:32:06 +00:00
dbms: development [#CONV-2944].
This commit is contained in:
parent
1197d447c4
commit
321475d215
@ -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;
|
||||
@ -299,6 +304,7 @@ 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;
|
||||
|
||||
|
@ -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));
|
||||
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user