Search Unity

HashMap is full

Discussion in 'Entity Component System' started by Desoxi, Apr 1, 2018.

  1. Desoxi

    Desoxi

    Joined:
    Apr 12, 2015
    Posts:
    195
    Hey there,

    im posting this for those around you who might have the same problem as i had just a few hours ago with
    NativeMultiHashMaps.
    As you may know you can create a NativeMultiHashMap like you would a NativeArray:

    Code (CSharp):
    1. multiHashMap = new NativeMultiHashMap<int, int>(lengthOfHashMap, Allocator.Persistent);
    And now you would happily add stuff into your MultiHashMap..., but why are you using NativeMultiHashMap and not the NativeHashMap instead? Well, its probably because you want to have "multiple" values bound to one key like this:


    Code (CSharp):
    1. multiHashMap.Add(0, 1);
    2. multiHashMap.Add(0, 2);
    3. multiHashMap.Add(0, 3);
    and so on (and yes you can have duplicates, its not a HashSet after all).

    And maybe you figured out how to iterate to say, all values of a specific key like this:

    Code (CSharp):
    1. int value;
    2. NativeMultiHashMapIterator<int> iterator;
    3.             if (neighbors.TryGetFirstValue(i, out value, out iterator))
    4.             {
    5.                 do
    6.                 {
    7.                     Debug.Log("KEY: " + 0 + " VALUE: " + value);
    8.                 } while (neighbors.TryGetNextValue(out value, ref iterator));
    9.             }
    Note that this is only logging values of the key '0'. You could add this in you job code or somewhere else and replace the 0 with the index to iterate over your MultiHashMap.

    Well, the thing now is, if you would fill for example 6 values for each key into your MultiHashMap and you allocated it like the very first code snippet above you will get an exception telling you that your HashMap is full. Why is that? Because exactly what it is telling you!
    You are filling 6 times more values into your Hashmap than you allocated memory for.
    To fix this, you only have to allocate the memory like this:

    Code (CSharp):
    1. multiHashMap = new NativeMultiHashMap<int, int>(lengthOfHashMap * 6, Allocator.Persistent);
    You may think it works like Dictionary<int, List<int>>, in which you could add an arbitrary amount of ints to your lists in whatever key, but its not. It has a fixed size and you have to keep that in mind.

    Hope this helps some of you, who might be searching for a solution to this kind of problem :)
     
    Last edited: Apr 29, 2018
    azmi_unity, Josp101, PaulUsul and 7 others like this.
  2. PlayingPolicy

    PlayingPolicy

    Joined:
    Dec 20, 2013
    Posts:
    15
    A question turned into another clarification. You do not need to over-allocate the hash maps to reduce collisions. It's handled internally. This may be obvious to many, but I seldom use hash tables. See NativeHashMap.cs:

    Code (CSharp):
    1. // Bucket size if [sic] bigger to reduce collisions
    2. NativeHashMapData.AllocateHashMap<TKey, TValue> (capacity, capacity*2, label, out m_Buffer);

    Also, to Unity, I'm pretty sure that "if" is supposed to say "is". Beware the typo got copy-pasted into two places.
     
  3. Antypodish

    Antypodish

    Joined:
    Apr 29, 2014
    Posts:
    10,780
    Plain and simple explanation. Thx

    I would just to ask, to ensure, we are up to date.
    Is this still ok approach, following latest ECS?
    Or anything new came up on the subject?