void SwapOrRemoveEntityComponents (EGID fromEntityGID, EGID?toEntityGID, IComponentBuilder[] entitiesToMove , FasterDictionary <RefWrapperType, ITypeSafeDictionary> fromGroup, in PlatformProfiler sampler)
public FasterDictionaryKeyValueEnumerator(FasterDictionary <TKey, TValue> dic) : this() { _dic = dic; _index = -1; _count = dic.Count; }
internal FasterDictionaryKeys(FasterDictionary <TKey, TValue> dic) : this() { }
void MoveEntityViewFromAndToEngines(EGID entityGID, EGID?toEntityGID, FasterDictionary <RefWrapper <Type>, ITypeSafeDictionary> fromGroup, FasterDictionary <RefWrapper <Type>, ITypeSafeDictionary> toGroup, Type entityViewType, in PlatformProfiler profiler)
public LocalFasterReadOnlyList <ExclusiveGroupStruct> FindGroups <T1, T2, T3, T4>() where T1 : IEntityComponent where T2 : IEntityComponent where T3 : IEntityComponent where T4 : IEntityComponent { FasterList <FasterDictionary <ExclusiveGroupStruct, ITypeSafeDictionary> > localArray = localgroups.Value.listOfGroups; if (groupsPerEntity.TryGetValue(TypeRefWrapper <T1> .wrapper, out localArray[0]) == false || localArray[0].count == 0) { return(new LocalFasterReadOnlyList <ExclusiveGroupStruct>( FasterReadOnlyList <ExclusiveGroupStruct> .DefaultEmptyList)); } if (groupsPerEntity.TryGetValue(TypeRefWrapper <T2> .wrapper, out localArray[1]) == false || localArray[1].count == 0) { return(new LocalFasterReadOnlyList <ExclusiveGroupStruct>( FasterReadOnlyList <ExclusiveGroupStruct> .DefaultEmptyList)); } if (groupsPerEntity.TryGetValue(TypeRefWrapper <T3> .wrapper, out localArray[2]) == false || localArray[2].count == 0) { return(new LocalFasterReadOnlyList <ExclusiveGroupStruct>( FasterReadOnlyList <ExclusiveGroupStruct> .DefaultEmptyList)); } if (groupsPerEntity.TryGetValue(TypeRefWrapper <T4> .wrapper, out localArray[3]) == false || localArray[3].count == 0) { return(new LocalFasterReadOnlyList <ExclusiveGroupStruct>( FasterReadOnlyList <ExclusiveGroupStruct> .DefaultEmptyList)); } localgroups.Value.groups.FastClear(); FasterDictionary <ExclusiveGroupStruct, ExclusiveGroupStruct> localGroups = localgroups.Value.groups; int startIndex = 0; int min = int.MaxValue; for (int i = 0; i < 4; i++) { if (localArray[i].count < min) { min = localArray[i].count; startIndex = i; } } foreach (var value in localArray[startIndex]) { if (value.key.IsEnabled()) { localGroups.Add(value.key, value.key); } } var groupData = localArray[++startIndex & 3]; //&3 == %4 localGroups.Intersect(groupData); if (localGroups.count == 0) { return(new LocalFasterReadOnlyList <ExclusiveGroupStruct>( FasterReadOnlyList <ExclusiveGroupStruct> .DefaultEmptyList)); } groupData = localArray[++startIndex & 3]; localGroups.Intersect(groupData); if (localGroups.count == 0) { return(new LocalFasterReadOnlyList <ExclusiveGroupStruct>( FasterReadOnlyList <ExclusiveGroupStruct> .DefaultEmptyList)); } groupData = localArray[++startIndex & 3]; localGroups.Intersect(groupData); return(new LocalFasterReadOnlyList <ExclusiveGroupStruct>(localGroups.unsafeValues , (uint)localGroups.count)); }
public void TestFasterDictionary() { FasterDictionary <int, Test> test = new FasterDictionary <int, Test>(); uint dictionarysize = 10000; int[] numbers = new int[dictionarysize]; for (int i = 1; i < dictionarysize; i++) { numbers[i] = numbers[i - 1] + i * HashHelpers.Expand((int)dictionarysize); } for (int i = 0; i < dictionarysize; i++) { test[i] = new Test(numbers[i]); } for (int i = 0; i < dictionarysize; i++) { if (test[i].i != numbers[i]) { throw new Exception(); } } for (int i = 0; i < dictionarysize; i += 2) { if (test.Remove(i) == false) { throw new Exception(); } } test.Trim(); for (int i = 0; i < dictionarysize; i++) { test[i] = new Test(numbers[i]); } for (int i = 1; i < dictionarysize - 1; i += 2) { if (test[i].i != numbers[i]) { throw new Exception(); } } for (int i = 0; i < dictionarysize; i++) { if (test[i].i != numbers[i]) { throw new Exception(); } } for (int i = (int)(dictionarysize - 1); i >= 0; i -= 3) { if (test.Remove(i) == false) { throw new Exception(); } } test.Trim(); for (int i = (int)(dictionarysize - 1); i >= 0; i -= 3) { test[i] = new Test(numbers[i]); } for (int i = 0; i < dictionarysize; i++) { if (test[i].i != numbers[i]) { throw new Exception(); } } for (int i = 0; i < dictionarysize; i++) { if (test.Remove(i) == false) { throw new Exception(); } } for (int i = 0; i < dictionarysize; i++) { if (test.Remove(i) == true) { throw new Exception(); } } test.Trim(); test.Clear(); for (int i = 0; i < dictionarysize; i++) { test[numbers[i]] = new Test(i); } for (int i = 0; i < dictionarysize; i++) { Test JapaneseCalendar = test[numbers[i]]; if (JapaneseCalendar.i != i) { throw new Exception("read back test failed"); } } }
public EntityComponentInitializer(EGID id, FasterDictionary <RefWrapperType, ITypeSafeDictionary> group) { _group = group; _ID = id; }
public EntityInitializer(EGID id, FasterDictionary <RefWrapperType, ITypeSafeDictionary> group, in EntityReference reference)
public bool MoveNext() { //attention, the while is necessary to skip empty groups while (_db.MoveNext() == true) { FasterDictionary <ExclusiveGroupStruct, ITypeSafeDictionary> .KeyValuePairFast group = _db.Current; ITypeSafeDictionary <T1> typeSafeDictionary = @group.Value as ITypeSafeDictionary <T1>; if (typeSafeDictionary.count == 0) { continue; } _array.collection = new EntityCollection <T1>(typeSafeDictionary.GetValues(out var count), count); _array.@group = new ExclusiveGroupStruct(group.Key); return(true); } return(false); }
public LegacyFilters( FasterDictionary <RefWrapperType, FasterDictionary <ExclusiveGroupStruct, LegacyGroupFilters> > filtersLegacy) { _filtersLegacy = filtersLegacy; }
public void RunGo() { var words = "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book.".Split(' '); var map = new NativeFasterDictionary <StringKey, SomeData>(100, Allocator.Persistent); var map2 = new NativeFasterDictionary <StringKey, SomeData>(100, Allocator.Persistent); var dict = new Dictionary <StringKey, SomeData>(100); var fdict = new FasterDictionary <StringKey, SomeData>(100); // I would test this against unity's NativeHashMap except they currently have no ability to set values by key :S try { for (int i = 0; i < words.Length; i++) { var key = new StringKey(words[i]); map[key] = new SomeData(); map2[key] = new SomeData(); dict[key] = new SomeData(); fdict[key] = new SomeData(); } var randomKeys = new StringKey[map.Length]; for (int i = 0; i < map.Length; i++) { var idx = UnityEngine.Random.Range(0, map.Length - 1); randomKeys[i] = new StringKey(words[idx]); } // Fair comparison assigning new value. NormalNativeDict(map, randomKeys); // Proper version using refs NormalNativeDictRef(map2, randomKeys); // Note the first time a job runs it's 10x slower. BurstJob(randomKeys, map); // Svelto's implementation. NormalFasterDict(fdict, randomKeys); // Stock standard C# NormalCSharpDict(dict, randomKeys); // Verify that the updates were correctly done for (int i = 0; i < words.Length; i++) { var key = new StringKey(words[i]); var id1 = map[key].Id; var id2 = map2[key].Id; var id3 = dict[key].Id; var id4 = fdict[key].Id; Debug.Assert(id1 == id2 && id1 == id3 && id1 == id4); var p1 = map[key].Position; var p2 = map2[key].Position; var p3 = dict[key].Position; var p4 = fdict[key].Position; Debug.Assert(p1 == p2 && p1 == p3 && p1 == p4); } Debug.Log("-----------------------------------------"); } catch (Exception e) { Debug.Log(e); throw; } finally { map.Dispose(); map2.Dispose(); } }
public TypeSafeDictionary() { _implementation = new FasterDictionary <uint, TValue>(1); }
public TypeSafeDictionary(uint size) { _implementation = new FasterDictionary <uint, TValue>(size); }
static void RemoveEntities (FasterDictionary <ExclusiveGroupStruct, FasterDictionary <RefWrapperType, FasterList <(uint, string)> > >
public EntityStructInitializer(EGID id, FasterDictionary <RefWrapper <Type>, ITypeSafeDictionary> group) { _group = group; _ID = id; }
void AddEntityViewsToTheDBAndSuitableEngines(DoubleBufferedEntitiesToAdd dbgroupsOfEntitiesToSubmit, PlatformProfiler profiler) { //each group is indexed by entity view type. for each type there is a dictionary indexed by entityID var groupsOfEntitiesToSubmit = dbgroupsOfEntitiesToSubmit.other; foreach (var groupOfEntitiesToSubmit in groupsOfEntitiesToSubmit) { var groupID = groupOfEntitiesToSubmit.Key; if (dbgroupsOfEntitiesToSubmit.otherEntitiesCreatedPerGroup.ContainsKey(groupID) == false) { continue; } //if the group doesn't exist in the current DB let's create it first if (_groupEntityDB.TryGetValue(groupID, out var groupDB) == false) { groupDB = _groupEntityDB[groupID] = new Dictionary <Type, ITypeSafeDictionary>(); } //add the entityViews in the group foreach (var entityViewsToSubmit in groupOfEntitiesToSubmit.Value) { var type = entityViewsToSubmit.Key; var typeSafeDictionary = entityViewsToSubmit.Value; if (groupDB.TryGetValue(type, out var dbDic) == false) { dbDic = groupDB[type] = typeSafeDictionary.Create(); } //Fill the DB with the entity views generate this frame. dbDic.AddEntitiesFromDictionary(typeSafeDictionary, groupID); if (_groupsPerEntity.TryGetValue(type, out var groupedGroup) == false) { groupedGroup = _groupsPerEntity[type] = new FasterDictionary <uint, ITypeSafeDictionary>(); } groupedGroup[groupID] = dbDic; } } //then submit everything in the engines, so that the DB is up to date with all the entity views and struct //created by the entity built using (profiler.Sample("Add entities to engines")) { foreach (var groupToSubmit in groupsOfEntitiesToSubmit) { var groupID = groupToSubmit.Key; var groupDB = _groupEntityDB[groupID]; foreach (var entityViewsPerType in groupToSubmit.Value) { var realDic = groupDB[entityViewsPerType.Key]; entityViewsPerType.Value.AddEntitiesToEngines(_reactiveEnginesAddRemove, realDic, ref profiler); } } } }
/// <summary> /// Note: unluckily I didn't design the serialization system to be component order independent, so unless /// I do something about it, this method cannot be optimized, the logic of the component order must stay /// untouched (no reordering, no use of dictionaries). Components order must stay as it comes, as /// well as extracomponents order. /// Speed, however, is not a big issue for this class, as the data is always composed once per entity descriptor /// at static constructor time /// </summary> /// <returns></returns> IComponentBuilder[] Construct(int extraComponentsLength, IComponentBuilder[] extraComponents) { IComponentBuilder[] MergeLists (IComponentBuilder[] startingComponents, IComponentBuilder[] newComponents, int newComponentsLength) { var startComponents = new FasterDictionary <RefWrapper <IComponentBuilder, ComponentBuilderComparer>, IComponentBuilder>(); var xtraComponents = new FasterDictionary <RefWrapper <IComponentBuilder, ComponentBuilderComparer>, IComponentBuilder>(); for (uint i = 0; i < startingComponents.Length; i++) { startComponents [new RefWrapper <IComponentBuilder, ComponentBuilderComparer>(startingComponents[i])] = startingComponents[i]; } for (uint i = 0; i < newComponentsLength; i++) { xtraComponents[new RefWrapper <IComponentBuilder, ComponentBuilderComparer>(newComponents[i])] = newComponents[i]; } xtraComponents.Exclude(startComponents); if (newComponentsLength != xtraComponents.count) { newComponentsLength = xtraComponents.count; uint index = 0; foreach (var couple in xtraComponents) { newComponents[index++] = couple.key.type; } } IComponentBuilder[] componentBuilders = new IComponentBuilder[newComponentsLength + startingComponents.Length]; Array.Copy(startingComponents, 0, componentBuilders, 0, startingComponents.Length); Array.Copy(newComponents, 0, componentBuilders, startingComponents.Length, newComponentsLength); var entityInfoComponentIndex = FetchEntityInfoComponent(componentBuilders); DBC.ECS.Check.Assert(entityInfoComponentIndex != -1); componentBuilders[entityInfoComponentIndex] = new ComponentBuilder <EntityInfoComponent>( new EntityInfoComponent { componentsToBuild = componentBuilders }); return(componentBuilders); } if (extraComponentsLength == 0) { return(_componentsToBuild); } var safeCopyOfExtraComponents = new IComponentBuilder[extraComponentsLength]; Array.Copy(extraComponents, safeCopyOfExtraComponents, extraComponentsLength); return(MergeLists(_componentsToBuild, safeCopyOfExtraComponents, extraComponentsLength)); }
internal EntitiesDB(FasterDictionary <int, Dictionary <Type, ITypeSafeDictionary> > groupEntityViewsDB, Dictionary <Type, FasterDictionary <int, ITypeSafeDictionary> > groupedGroups) { _groupEntityViewsDB = groupEntityViewsDB; _groupedGroups = groupedGroups; }
public Filters (FasterDictionary <RefWrapperType, FasterDictionary <ExclusiveGroupStruct, GroupFilters> > filters) { _filters = filters; }
//[InlineData(5_000_000)] public async Task AddIterateUpdateIterateKeys(int loops, CheckpointType checkpointType) { var options = GetOptions($"{nameof(AddIterateUpdateIterate)}-{loops}"); options.CheckPointType = checkpointType; options.DeleteOnClose = false; FasterDictionary <int, string> .ReadResult result; using (var dictionary = new FasterDictionary <int, string>(TestHelper.GetKeyComparer <int>(), options)) { for (var i = 0; i < loops; i++) { dictionary.Upsert(i, (i + 1).ToString()).Dismiss(); } await dictionary.Ping(); await dictionary.Save(); } var count = 0; using (var dictionary = new FasterDictionary <int, string>(TestHelper.GetKeyComparer <int>(), options)) { for (var i = 0; i < 100; i++) { result = await dictionary.TryGet(i); Assert.True(result.Found); Assert.Equal((result.Key + 1).ToString(), result.Value); } await foreach (var entry in dictionary.AsKeysIterator()) { count++; } result = await dictionary.TryGet(loops); Assert.False(result.Found); Assert.Equal(loops, count); } count = 0; using (var dictionary = new FasterDictionary <int, string>(TestHelper.GetKeyComparer <int>(), options)) { for (var i = 0; i < loops; i++) { if (i % 4 == 0) { dictionary.Remove(i).Dismiss(); } else { count++; dictionary.Upsert(i, (i + 2).ToString()).Dismiss(); } } await dictionary.Ping(); await dictionary.Save(); } options.DeleteOnClose = true; using (var dictionary = new FasterDictionary <int, string>(TestHelper.GetKeyComparer <int>(), options)) { for (var i = 0; i < 100; i++) { result = await dictionary.TryGet(i); if (i % 4 == 0) { Assert.False(result.Found); } else { Assert.True(result.Found); Assert.Equal((result.Key + 2).ToString(), result.Value); } } var loopCount = 0; await foreach (var entry in dictionary.AsKeysIterator()) { loopCount++; Assert.False(entry % 4 == 0); } result = await dictionary.TryGet(loops); Assert.False(result.Found); Assert.Equal(loopCount, count); } }