[serializer] Don't hash objects twice
This commit is contained in:
parent
35878df215
commit
3d1c76f713
|
@ -198,14 +198,49 @@ struct hb_hashmap_t
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename VV>
|
||||||
|
bool set_with_hash (K key, uint32_t hash, VV&& value, bool is_delete=false)
|
||||||
|
{
|
||||||
|
if (unlikely (!successful)) return false;
|
||||||
|
if (unlikely ((occupancy + occupancy / 2) >= mask && !resize ())) return false;
|
||||||
|
item_t &item = item_for_hash (key, hash);
|
||||||
|
|
||||||
|
if (is_delete && !(item == key))
|
||||||
|
return true; /* Trying to delete non-existent key. */
|
||||||
|
|
||||||
|
if (item.is_used ())
|
||||||
|
{
|
||||||
|
occupancy--;
|
||||||
|
if (!item.is_tombstone ())
|
||||||
|
population--;
|
||||||
|
}
|
||||||
|
|
||||||
|
item.key = key;
|
||||||
|
item.value = std::forward<VV> (value);
|
||||||
|
item.hash = hash;
|
||||||
|
item.set_used (true);
|
||||||
|
item.set_tombstone (is_delete);
|
||||||
|
|
||||||
|
occupancy++;
|
||||||
|
if (!is_delete)
|
||||||
|
population++;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
template <typename VV>
|
template <typename VV>
|
||||||
bool set (K key, VV&& value) { return set_with_hash (key, hb_hash (key), std::forward<VV> (value)); }
|
bool set (K key, VV&& value) { return set_with_hash (key, hb_hash (key), std::forward<VV> (value)); }
|
||||||
|
|
||||||
|
const V& get_with_hash (K key, uint32_t hash) const
|
||||||
|
{
|
||||||
|
if (unlikely (!items)) return item_t::default_value ();
|
||||||
|
auto &item = item_for_hash (key, hash);
|
||||||
|
return item.is_real () && item == key ? item.value : item_t::default_value ();
|
||||||
|
}
|
||||||
const V& get (K key) const
|
const V& get (K key) const
|
||||||
{
|
{
|
||||||
if (unlikely (!items)) return item_t::default_value ();
|
if (unlikely (!items)) return item_t::default_value ();
|
||||||
auto &item = item_for (key);
|
return get_with_hash (key, hb_hash (key));
|
||||||
return item.is_real () && item == key ? item.value : item_t::default_value ();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void del (K key) { set_with_hash (key, hb_hash (key), item_t::default_value (), true); }
|
void del (K key) { set_with_hash (key, hb_hash (key), item_t::default_value (), true); }
|
||||||
|
@ -218,7 +253,7 @@ struct hb_hashmap_t
|
||||||
{
|
{
|
||||||
if (unlikely (!items))
|
if (unlikely (!items))
|
||||||
return false;
|
return false;
|
||||||
auto &item = item_for (key);
|
auto &item = item_for_hash (key, hb_hash (key));
|
||||||
if (item.is_real () && item == key)
|
if (item.is_real () && item == key)
|
||||||
{
|
{
|
||||||
if (vp) *vp = std::addressof (item.value);
|
if (vp) *vp = std::addressof (item.value);
|
||||||
|
@ -322,43 +357,6 @@ struct hb_hashmap_t
|
||||||
hb_hashmap_t& operator << (const hb_pair_t<K&&, V&&>& v)
|
hb_hashmap_t& operator << (const hb_pair_t<K&&, V&&>& v)
|
||||||
{ set (std::move (v.first), std::move (v.second)); return *this; }
|
{ set (std::move (v.first), std::move (v.second)); return *this; }
|
||||||
|
|
||||||
protected:
|
|
||||||
|
|
||||||
template <typename VV>
|
|
||||||
bool set_with_hash (K key, uint32_t hash, VV&& value, bool is_delete=false)
|
|
||||||
{
|
|
||||||
if (unlikely (!successful)) return false;
|
|
||||||
if (unlikely ((occupancy + occupancy / 2) >= mask && !resize ())) return false;
|
|
||||||
item_t &item = item_for_hash (key, hash);
|
|
||||||
|
|
||||||
if (is_delete && !(item == key))
|
|
||||||
return true; /* Trying to delete non-existent key. */
|
|
||||||
|
|
||||||
if (item.is_used ())
|
|
||||||
{
|
|
||||||
occupancy--;
|
|
||||||
if (!item.is_tombstone ())
|
|
||||||
population--;
|
|
||||||
}
|
|
||||||
|
|
||||||
item.key = key;
|
|
||||||
item.value = std::forward<VV> (value);
|
|
||||||
item.hash = hash;
|
|
||||||
item.set_used (true);
|
|
||||||
item.set_tombstone (is_delete);
|
|
||||||
|
|
||||||
occupancy++;
|
|
||||||
if (!is_delete)
|
|
||||||
population++;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
item_t& item_for (const K &key) const
|
|
||||||
{
|
|
||||||
return item_for_hash (key, hb_hash (key));
|
|
||||||
}
|
|
||||||
|
|
||||||
item_t& item_for_hash (const K &key, uint32_t hash) const
|
item_t& item_for_hash (const K &key, uint32_t hash) const
|
||||||
{
|
{
|
||||||
hash &= 0x3FFFFFFF; // We only store lower 30bit of hash
|
hash &= 0x3FFFFFFF; // We only store lower 30bit of hash
|
||||||
|
|
|
@ -354,9 +354,11 @@ struct hb_serialize_context_t
|
||||||
}
|
}
|
||||||
|
|
||||||
objidx_t objidx;
|
objidx_t objidx;
|
||||||
|
uint32_t hash;
|
||||||
if (share)
|
if (share)
|
||||||
{
|
{
|
||||||
objidx = packed_map.get (obj);
|
hash = hb_hash (obj);
|
||||||
|
objidx = packed_map.get_with_hash (obj, hash);
|
||||||
if (objidx)
|
if (objidx)
|
||||||
{
|
{
|
||||||
merge_virtual_links (obj, objidx);
|
merge_virtual_links (obj, objidx);
|
||||||
|
@ -384,7 +386,7 @@ struct hb_serialize_context_t
|
||||||
|
|
||||||
objidx = packed.length - 1;
|
objidx = packed.length - 1;
|
||||||
|
|
||||||
if (share) packed_map.set (obj, objidx);
|
if (share) packed_map.set_with_hash (obj, hash, objidx);
|
||||||
propagate_error (packed_map);
|
propagate_error (packed_map);
|
||||||
|
|
||||||
return objidx;
|
return objidx;
|
||||||
|
|
|
@ -232,7 +232,7 @@ main (int argc, char **argv)
|
||||||
// See commit f657ef7e57c889309c2d9d37934368ca255f9d5b and its revert.
|
// See commit f657ef7e57c889309c2d9d37934368ca255f9d5b and its revert.
|
||||||
//m.set (hb::unique_ptr<hb_set_t> (hb_set_get_empty ()),
|
//m.set (hb::unique_ptr<hb_set_t> (hb_set_get_empty ()),
|
||||||
// hb::unique_ptr<hb_set_t> (hb_set_get_empty ()));
|
// hb::unique_ptr<hb_set_t> (hb_set_get_empty ()));
|
||||||
m.get (hb::unique_ptr<hb_set_t> (hb_set_get_empty ()));
|
//m.get (hb::unique_ptr<hb_set_t> (hb_set_get_empty ()));
|
||||||
m.iter_ref ();
|
m.iter_ref ();
|
||||||
m.keys_ref ();
|
m.keys_ref ();
|
||||||
m.values_ref ();
|
m.values_ref ();
|
||||||
|
|
Loading…
Reference in New Issue