Skip to content

Commit

Permalink
fixup
Browse files Browse the repository at this point in the history
  • Loading branch information
akuzm committed Oct 18, 2019
1 parent 59f92eb commit 6232528
Show file tree
Hide file tree
Showing 5 changed files with 78 additions and 58 deletions.
37 changes: 26 additions & 11 deletions dbms/src/Common/HashTable/StringHashMap.h
Expand Up @@ -80,10 +80,18 @@ class StringHashMap : public StringHashTable<StringHashMapSubMaps<TMapped, Alloc
template <typename Func>
void ALWAYS_INLINE mergeToViaEmplace(Self & that, Func && func)
{
if (this->m0.size() && that.m0.size())
func(that.m0.value.getSecond(), this->m0.value.getSecond(), false);
else if (this->m0.size())
func(that.m0.value.getSecond(), this->m0.value.getSecond(), true);
if (this->m0.hasZero())
{
const bool emplace_new_zero = !that.m0.hasZero();
if (emplace_new_zero)
{
that.m0.setHasZero();
}

func(that.m0.zeroValue()->getSecond(), this->m0.zeroValue()->getSecond(),
emplace_new_zero);
}

this->m1.mergeToViaEmplace(that.m1, func);
this->m2.mergeToViaEmplace(that.m2, func);
this->m3.mergeToViaEmplace(that.m3, func);
Expand All @@ -98,10 +106,18 @@ class StringHashMap : public StringHashTable<StringHashMapSubMaps<TMapped, Alloc
template <typename Func>
void ALWAYS_INLINE mergeToViaFind(Self & that, Func && func)
{
if (this->m0.size() && that.m0.size())
func(that.m0.value.getSecond(), this->m0.value.getSecond(), true);
else if (this->m0.size())
func(this->m0.value.getSecond(), this->m0.value.getSecond(), false);
if (this->m0.hasZero())
{
if (that.m0.hasZero())
{
func(that.m0.zeroValue()->getSecond(), this->m0.zeroValue()->getSecond(), true);
}
else
{
func(this->m0.zeroValue()->getSecond(), this->m0.zeroValue()->getSecond(), false);
}
}

this->m1.mergeToViaFind(that.m1, func);
this->m2.mergeToViaFind(that.m2, func);
this->m3.mergeToViaFind(that.m3, func);
Expand All @@ -123,8 +139,7 @@ class StringHashMap : public StringHashTable<StringHashMapSubMaps<TMapped, Alloc
{
if (this->m0.size())
{
auto v = this->m0.value;
func(toStringRef(v.getFirst()), v.getSecond());
func(StringRef{}, this->m0.zeroValue()->getSecond());
}

for (auto & v : this->m1)
Expand Down Expand Up @@ -152,7 +167,7 @@ class StringHashMap : public StringHashTable<StringHashMapSubMaps<TMapped, Alloc
void ALWAYS_INLINE forEachMapped(Func && func)
{
if (this->m0.size())
func(this->m0.value.getSecond());
func(this->m0.zeroValue()->getSecond());
for (auto & v : this->m1)
func(v.getSecond());
for (auto & v : this->m2)
Expand Down
60 changes: 43 additions & 17 deletions dbms/src/Common/HashTable/StringHashTable.h
Expand Up @@ -124,38 +124,64 @@ template <typename Cell>
struct StringHashTableEmpty
{
using Self = StringHashTableEmpty;
using LookupResult = typename Cell::mapped_type *;

Cell value;
bool is_empty{true};
bool has_zero = false;
std::aligned_storage_t<sizeof(Cell), alignof(Cell)> zero_value_storage; /// Storage of element with zero key.

StringHashTableEmpty() { memset(reinterpret_cast<char *>(&value), 0, sizeof(value)); }
public:
bool hasZero() const { return has_zero; }

void setHasZero()
{
has_zero = true;
new (zeroValue()) Cell();
}

void setHasZero(const Cell & other)
{
has_zero = true;
new (zeroValue()) Cell(other);
}

void ALWAYS_INLINE emplace(const StringKey0 &, LookupResult & it, bool & inserted, size_t)
void clearHasZero()
{
has_zero = false;
if (!std::is_trivially_destructible_v<Cell>)
zeroValue()->~Cell();
}

Cell * zeroValue() { return reinterpret_cast<Cell *>(&zero_value_storage); }
const Cell * zeroValue() const { return reinterpret_cast<const Cell *>(&zero_value_storage); }

if (is_empty)
using LookupResult = Cell *;
using ConstLookupResult = const Cell *;

template <typename KeyHolder>
void ALWAYS_INLINE emplace(KeyHolder &&, LookupResult & it, bool & inserted, size_t /* hash */)
{
if (!hasZero())
{
setHasZero();
inserted = true;
is_empty = false;
}
else
inserted = false;

it = &value.getSecond();
it = zeroValue();
}

LookupResult ALWAYS_INLINE find(const StringKey0 &, size_t)
template <typename Key>
LookupResult ALWAYS_INLINE find(Key, size_t /* hash */)
{
return &value.getSecond();
return hasZero() ? zeroValue() : nullptr;
}

void write(DB::WriteBuffer & wb) const { value.write(wb); }
void writeText(DB::WriteBuffer & wb) const { value.writeText(wb); }
void read(DB::ReadBuffer & rb) { value.read(rb); }
void readText(DB::ReadBuffer & rb) { value.readText(rb); }
size_t size() const { return is_empty ? 0 : 1; }
bool empty() const { return is_empty; }

void write(DB::WriteBuffer & wb) const { zeroValue()->write(wb); }
void writeText(DB::WriteBuffer & wb) const { zeroValue()->writeText(wb); }
void read(DB::ReadBuffer & rb) { zeroValue()->read(rb); }
void readText(DB::ReadBuffer & rb) { zeroValue()->readText(rb); }
size_t size() const { return hasZero() ? 1 : 0; }
bool empty() const { return !hasZero(); }
size_t getBufferSizeInBytes() const { return sizeof(Cell); }
size_t getCollisions() const { return 0; }
};
Expand Down
36 changes: 9 additions & 27 deletions dbms/src/Common/HashTable/TwoLevelStringHashTable.h
Expand Up @@ -40,11 +40,9 @@ class TwoLevelStringHashTable : private boost::noncopyable
template <typename Source>
TwoLevelStringHashTable(const Source & src)
{
if (src.m0.size())
{
impls[0].m0.value = src.m0.value;
impls[0].m0.is_empty = false;
}
if (src.m0.hasZero())
impls[0].m0.setHasZero(*src.m0.zeroValue());

for (auto & v : src.m1)
{
size_t hash_value = v.getHash(src.m1);
Expand Down Expand Up @@ -95,6 +93,7 @@ class TwoLevelStringHashTable : private boost::noncopyable
StringKey24 k24;
UInt64 n[3];
};
StringHashTableHash hash;
switch (sz)
{
case 0:
Expand All @@ -113,52 +112,35 @@ class TwoLevelStringHashTable : private boost::noncopyable
memcpy(&n[0], lp, 8);
n[0] >>= s;
}
res = _mm_crc32_u64(res, n[0]);
res = hash(k8);
buck = getBucketFromHash(res);
keyHolderDiscardKey(key_holder);
return func(impls[buck].m1, k8, res);
}
CASE_9_16 : {
memcpy(&n[0], p, 8);
res = _mm_crc32_u64(res, n[0]);
const char * lp = x.data + x.size - 8;
memcpy(&n[1], lp, 8);
n[1] >>= s;
res = _mm_crc32_u64(res, n[1]);
res = hash(k16);
buck = getBucketFromHash(res);
keyHolderDiscardKey(key_holder);
return func(impls[buck].m2, k16, res);
}
CASE_17_24 : {
memcpy(&n[0], p, 16);
res = _mm_crc32_u64(res, n[0]);
res = _mm_crc32_u64(res, n[1]);
const char * lp = x.data + x.size - 8;
memcpy(&n[2], lp, 8);
n[2] >>= s;
res = _mm_crc32_u64(res, n[2]);
res = hash(k24);
buck = getBucketFromHash(res);
keyHolderDiscardKey(key_holder);
return func(impls[buck].m3, k24, res);
}
default: {
memcpy(&n, x.data, 24);
res = _mm_crc32_u64(res, n[0]);
res = _mm_crc32_u64(res, n[1]);
res = _mm_crc32_u64(res, n[2]);
p += 24;
const char * lp = x.data + x.size - 8;
while (p + 8 < lp)
{
memcpy(&n[0], p, 8);
res = _mm_crc32_u64(res, n[0]);
p += 8;
}
memcpy(&n[0], lp, 8);
n[0] >>= s;
res = _mm_crc32_u64(res, n[0]);
res = hash(x);
buck = getBucketFromHash(res);
return func(impls[buck].ms, key_holder, res);
return func(impls[buck].ms, std::forward<KeyHolder>(key_holder), res);
}
}
}
Expand Down

This file was deleted.

1 change: 0 additions & 1 deletion dbms/tests/queries/0_stateless/00960_string_hash_map.sql

This file was deleted.

0 comments on commit 6232528

Please sign in to comment.