简体   繁体   English

当您有 10 万到一百万个对象/索引时,维护脏对象或索引列表的有效方法是什么?

[英]What's an efficient way of maintaining a list of dirty objects or indexes when you have 100k to a Million objects/indexes?

I have to iterate over +100k objects in real-time (for a video game).我必须实时迭代超过 10 万个对象(对于视频游戏)。

To make things faster, I implemented a HashSet<int> DirtyIndexes and whenever an object is modified, I do DirtyIndexes.Add(index) and iterate over those indexes only.为了使事情更快,我实现了一个HashSet<int> DirtyIndexes并且每当一个对象被修改时,我都会执行DirtyIndexes.Add(index)并只迭代这些索引。

Unfortunately HashSet.Add() 's duplicate check is kinda slow and, at 10k+ objects per frame, the process of adding that many indexes kills any advantage of using this system.不幸的是HashSet.Add()的重复检查有点慢,并且在每帧 10k+ 个对象的情况下,添加这么多索引的过程会扼杀使用该系统的任何优势。

I was hoping to find a collection that allowed multiple objects to share a key and would return an array of everything that matches the search key, but couldn't find anything.我希望找到一个集合,该集合允许多个对象共享一个键,并返回与搜索键匹配的所有内容的数组,但找不到任何内容。

Another idea is to use an int array of the same size as the number of objects and set 0 for clean, 1 for dirty, but then I have to add several Ifs to my code to filter out indexes, which would also slow things down.另一个想法是使用与对象数量相同大小的 int 数组,并设置 0 表示干净,1 表示脏,但是我必须在代码中添加几个 If 以过滤掉索引,这也会减慢速度。

I could also add the dirty objects to a DirtyObject list, but then I once again have to prevent duplicates and end up with the same problem.我也可以将脏对象添加到 DirtyObject 列表中,但是我再次必须防止重复并最终遇到相同的问题。

Does anyone have a solution to this?有没有人有解决方案?

For efficiency its better to use an array than a list.为了效率,使用数组比使用列表更好。 If you want to use the features of the List class but to use the array when needed, you can use a class that has an array and a list as class variables, and update the array only when the list is changed, like this:如果你想使用List类的特性,但在需要时使用数组,你可以使用一个具有数组和列表的类作为类变量,并且只在列表改变时更新数组,如下所示:

using System;
using System.Collections.Generic;

public class CustomList<T>
{
    //private
    bool _isDirty;
    List<T> _list;
    T[] _array;

    //public
    T[] getArray() {
        if (_isDirty)
            _array = _list.ToArray();
        return _array;
    }

    //handler methods
    public CustomList() {
        _list = new List<T>();
    }

    public void Add(T item) {
        _list.Add(item);
        _isDirty = true;
    }

    public void Remove(T item) {
        _list.Remove(item);
        _isDirty = true;
    }

    public void RemoveAt(int i) {
        _list.RemoveAt(i);
        _isDirty = true;
    }

    public bool Contains(T item) {
        return _list.Contains(item);
    }

    public int Count() {
        return _list.Count;
    }

    public T this[int index] {
        get { return _list[index]; }
        set { _list[index] = value; }
    }

    public void Clear() {
        _list.Clear();
        _isDirty = true;
    }

    public void RemoveAll(Predicate<T> predicate) {
        _list.RemoveAll(predicate);
        _isDirty = true;
    }

    public T Find(Predicate<T> predicate) {
        return _list.Find(predicate);
    }

    public void Insert(int index, T item) {
        _list.Insert(index, item);
        _isDirty = true;
    }

    public void ForEach(Action<T> action) {
        _list.ForEach(action);
    }
}

You might as well use a List<int> for DirtyObjects , since List<T> is essentially just an array with quality of life features on top of it, and you can iterate over it very quickly.您也可以将List<int>用于DirtyObjects ,因为List<T>本质上只是一个具有生活质量特征的数组,您可以非常快速地对其进行迭代。

As for preventing duplicates, you could maintain a bool isDirty flag in each object and only add an object to the list if its flag isn't already set:至于防止重复,您可以在每个对象中维护一个bool isDirty标志,如果尚未设置其标志,则仅将对象添加到列表中:

private void OnChanged() {
    if (!this.isDirty) {
        this.isDirty = true;
        DirtyObjects.Add(this.index);
    }
}

This would prevent any object from being added to DirtyObjects more than once.这将防止任何对象DirtyObjects添加到DirtyObjects (And it doesn't have to do any kind of lookup in the process!) This logic also doesn't need to be particularly fast, since it's only executed whenever a clean object becomes dirty. (而且它不必在过程中进行任何类型的查找!)这个逻辑也不需要特别快,因为它只在干净的对象变脏时才执行。

Then whatever code eventually "cleans up" the dirty objects can set their isDirty flags back to false , and the cycle continues.然后无论代码最终“清理”脏对象,都可以将它们的isDirty标志设置回false ,然后循环继续。

You guys made excellent suggestions, but running with this many entities, I had to come up with something else.你们提出了很好的建议,但是与这么多实体一起运行,我不得不想出其他办法。

The secret is to use 2 arrays.秘诀是使用 2 个数组。 One for the value and the second one for its dirty flag (0 or 1).一个是值,第二个是脏标志(0 或 1)。 This prevents duplicates (doesn't matter if the value is set dirty multiple times) and is much faster.这可以防止重复(如果多次将值设置为脏值无关紧要)并且速度要快得多。 Both arrays are initialized ahead of time to my pool size.两个数组都提前初始化为我的池大小。

The idea is to use a set of array like this for every value I want to iterate through.这个想法是对我想要迭代的每个值使用一组这样的数组。 Doing it this way allows processing the data at different rates while maintaining compatibility with Unity's Job system.这样做允许以不同的速率处理数据,同时保持与 Unity 的作业系统的兼容性。

Burst is amazing, Vectorization, you are next!爆发是惊人的,矢量化,你是下一个!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 当您有对象ID列表时,有效的linq查询返回对象 - Efficient linq query to return objects when you have a list of object id's 访问列表中的两个索引并使用Linq创建新对象的列表 - Access two indexes in a list and create a list of new objects using Linq 将文本的特定部分子串化为对象列表的最有效方法是什么 - What is the most efficient way to substring specific portions of a text to a list of objects 我有一个超过一百万个对象的列表,试图找到最快的搜索方式 - I have a list with over a million objects in it, trying to find the fastest way to search through it 使用c#删除大量(&gt; 100K)文件,同时保持Web应用程序的性能? - Delete a large number (>100K) of files with c# whilst maintaining performance in a web application? 为什么对象不知道自己的索引? - Why don't objects know their own indexes? 当您将对象数组转换为字符串数组时,这叫什么? - What's it called when you cast an array of objects to an array of strings? 在C#中返回对象列表的最快方法是什么? - What's the fastest way to return a list of objects in C#? 在对象列表中打印所有属性的最佳方法是什么? - What's the best way to print all properties in a list of objects? 编译子对象列表中所有父对象列表的最佳方法是什么? - What's the best way to compile a list of all Parent objects of a list of child objects?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM