#Avoid copy of `NativeHashMap` element

1 messages · Page 1 of 1 (latest)

sour glacier
#

In the in parameter blog article (https://blog.unity.com/engine-platform/in-parameters-in-burst), one recommendation for avoiding array element copies is to use ref UnsafeUtility.ArrayElementAsRef<T>(array.GetUnsafePtr(), index) when reading from a NativeArray<T>.

Is there a way to do the same for a NativeHashMap<int, T>? The GetUnsafePtr() method seems to be missing here, and I haven't figured out how to work around that.

latent shuttle
#

getunsafeptr doesn't really make much sense for a hashmap

#

because there are '4 pointers'

#

keys, values, buckets, next

#

@rugged osprey does have a ref enumerator somewhere though

#

alternatively if you want to return a value by ref i do have extensions for that

#
        public static ref TValue GetValueByRef<TKey, TValue>(this NativeParallelHashMap<TKey, TValue> map, TKey key)
            where TKey : unmanaged, IEquatable<TKey>
            where TValue : unmanaged
#

or just

public static ref TValue GetOrAddRef<TKey, TValue>(this NativeHashMap<TKey, TValue> hashMap, TKey key)
            where TKey : unmanaged, IEquatable<TKey>
            where TValue : unmanaged```
sour glacier
#

oh wow mr tertle himself! thanks! that looks exactly like what i'm looking for!

#

i'll give it a go and report back.

#

also, awesome stuff @rugged osprey, i didn't know about nzcore

rugged osprey
#

thanks 😄 it's a pretty small library compared to what tertle has but lots of useful stuff when it comes to data containers

sour glacier
#

@latent shuttle i was wondering how that would work when i first looked at that line

#

how does that work within bovinelabs.core?

latent shuttle
#

because core has internal access to the entities package

#

it's calling this under the hood btw

#
        internal static ref TValue GetValueByRef<TKey, TValue>(this ref UnsafeParallelHashMapData data, TKey key)
            where TKey : struct, IEquatable<TKey>
            where TValue : struct
        {
#if ENABLE_UNITY_COLLECTIONS_CHECKS
            if (data.allocatedIndexLength <= 0)
            {
                throw new KeyNotFoundException();
            }
#endif

            // First find the slot based on the hash
            var buckets = (int*)data.buckets;
            var bucket = key.GetHashCode() & data.bucketCapacityMask;
            var entryIdx = buckets[bucket];

            var nextPtrs = (int*)data.next;
            while (!UnsafeUtility.ReadArrayElement<TKey>(data.keys, entryIdx).Equals(key))
            {
                entryIdx = nextPtrs[entryIdx];
#if ENABLE_UNITY_COLLECTIONS_CHECKS
                if ((entryIdx < 0) || (entryIdx >= data.keyCapacity))
                {
                    throw new KeyNotFoundException();
                }
#endif
            }

            // Read the value
            return ref UnsafeUtility.ArrayElementAsRef<TValue>(data.values, entryIdx);
        }
#

so you can't just 'take' the first simply method

#

it's not the implementation

#

you will need to do this for any extensions

sour glacier
#

you're right, i gotta familiarize myself with this. adding the openupm package to my project should work though, right?

latent shuttle
#

for core?

#

yeah should be update to date with entities 1.1

#

(stick with core 1.0 if you're still on 1.0.16)

sour glacier
#

i'm actually migrating away from entities to only jobs+burst

latent shuttle
#

ah interesting

sour glacier
#

so, for the injection to work, is there anything else needed apart from creating the assemblyinfo.cs? i guess it has to be linked somewhere in the project as such?

latent shuttle
#

the asmref in that folder

#

is what allows you to add files to another package

#

using this you put an assemblyinfo into the package you want (i.e. collections) and make it give you internal access

sour glacier
#

awesome, that seemed to work!

#

okay, the implementation works, too! dude, thanks a million times! ❤️

latent shuttle
#

👍